javascript - 在类组件的方法中获取查询

标签 javascript reactjs graphql react-apollo apollo-client

带有反应的 Apollo 客户端 (2.6.3)。 是否可以在类组件的方法中获取数据? 我正在构建一个全局搜索组件,并且我只想在键入第 3 个(和每个后续)字符时获取数据。现在它是用 fetch api 实现的,但我想切换到 apollo 客户端和 graphql api。

直到这一刻,我还没有遇到任何关于 apollo 客户端 API 的问题,因为我使用 <Query/>组件。

我尝试使用新的 hooks api,但事实证明 useLazyQuery() 只能在函数组件中使用(hooks 规则)。

这是我到目前为止所做的。我知道那个组件很乱,我愿意接受建议。这是我的第一个 React 应用。

import React, { Component } from "react";
import PropTypes from "prop-types";
import { Select, Icon, Button } from "antd";
import { es } from "../../../utils/queries";
import { useLazyQuery } from "@apollo/react-hooks";

const { Option, OptGroup } = Select;

class GlobalSearch extends Component {
  constructor(props) {
    super(props);
    this.searchInput = React.createRef();
  }

  state = {
    data: [],
    value: undefined,
    display: false
  };

  componentDidMount() {
    document.addEventListener("click", this.onClickOutside);
  }

  generateOptions(data) {
    return data.map(d => {
      if (d._index === "cases") {
        d.label = (
          <div>
            <Icon style={{ fontSize: "18px" }} type="tool" />
            <span style={{ color: "#183247" }}>
              {d._source.number + d._source.serialNumber}
            </span>
          </div>
        );
      } else if (d._index === "items") {
        d.label = (
          <div>
            <Icon style={{ fontSize: "18px" }} type="barcode-o" />
            <span style={{ color: "#183247" }}>{d._source.name}</span>
          </div>
        );
      } else if (d._index === "people") {
        d.label = (
          <div>
            <Icon
              type="user"
              style={{ fontSize: "18px", float: "left", marginTop: "3px" }}
            />
            <div style={{ marginLeft: "26px" }}>
              <span style={{ color: "#183247" }}>
                {" "}
                <div>{d._source.name + " " + d._source.surname}</div>
              </span>
              <div>{d._source.email}</div>
            </div>
          </div>
        );
      } else if (d._index === "counterparties") {
        d.label = (
          <div>
            <Icon style={{ fontSize: "18px" }} type="shop" />
            <span style={{ color: "#183247" }}>{d._source.name}</span>
          </div>
        );
      } else {
        d.label = "undefined";
      }
      return d;
    });
  }

  //group data according to type of the search result (index e.g. cases, items, contacts)
  setData = es_data => {
    const data = {};
    const map = new Map();
    for (const item of es_data) {
      if (!map.has(item._index)) {
        map.set(item._index);

        data[item._index] = [];
      }
      data[item._index].push(item);
    }

    this.setState({ data: data });
  };

  handleSearch = value => {
    if (value.length > 2) {
      //tutaj wyszukujemy dane na serwerze a wyniki callbackiem przesyłamy do state.data[]
      //response.json() calls mixin methods from body
      
      const host = window.location.hostname

      // const { loading, data } = useLazyQuery(es(value));
      // if (loading) return undefined;

      // if (data) {
      //   this.setData(this.generateOptions(data));
      // }

      fetch(`http://${host}:3000/api/es?searchString=${value}`)
        .then(response => response.json())
        .then(es_data => {
          this.setData(this.generateOptions(es_data));
        });
    }
  };

  handleChange = value => {
    //przy kazdym wpisanym znaku aktualizuj wartosc pola
    this.setState({ value });
  };

  handleSelect = (key, option) => {
    console.log(key);
    console.log(option);
  };

  handleBlur = e => {
    this.setState({ display: false, value: undefined, data: [] });
  };

  onClick = () => {
    this.setState({ display: !this.state.display });
  };

  getSearchField(options) {
    if (this.state.display) {
      return (
        <Select
          id="global-search-field"
          optionLabelProp="label"
          showSearch
          value={this.state.value}
          placeholder={"search..."}
          style={{ display: this.state.display, width: "350px" }}
          defaultActiveFirstOption={true}
          showArrow={false}
          filterOption={false}
          onSearch={this.handleSearch}
          onChange={this.handleChange}
          onSelect={this.handleSelect}
          notFoundContent={"nothing here..."}
          onBlur={this.handleBlur}
          autoFocus={true}
          showAction={["focus"]}
          dropdownClassName="global-search-dropdown"
        >
          {options}
        </Select>
      );
    }
  }

  render() {
    //generate options for each group (index)
    const options = Object.keys(this.state.data).map(d => (
      <OptGroup label={d}>
        {this.state.data[d].map(d => (
          <Option
            className={d._index}
            type={d._index}
            key={d._id}
            label={d.label}
          >
            <div>{d.label}</div>
          </Option>
        ))}
      </OptGroup>
    ));

    return (
      <span>
        {this.getSearchField(options)}

        <Button
          id="global-search"
          shape="circle"
          icon="search"
          onClick={this.onClick}
        />
      </span>
    );
  }
}

export default GlobalSearch;

最佳答案

Apollo Client 提供了一个基于 Promise 的 API,可以对您的查询/变更运行的时间/地点提供更多命令式控制。这是来自 their docs 的示例:

client
  .query({
    query: gql`
      query GetLaunch {
        launch(id: 56) {
          id
          mission {
            name
          }
        }
      }
    `,
    variables: { ... }
  })
  .then(result => console.log(result));

您可以导入您的客户端并在任何方法或函数中使用此模式,就像使用 Promises 的任何其他异步操作一样。

关于javascript - 在类组件的方法中获取查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57874784/

相关文章:

javascript - D3 中的水平条形图条形标签

reactjs - React 16.4 基于 Promise 的条件渲染

html - 我们如何通过在 ReactJs (Jsx) 中使用 <div> 来破坏 HTML 语义

reactjs - Gatsby 在 graphql 查询返回后获取图像路径

graphql - Apollo GraphQL - 处理 onConnect 和 OnDisconnect 事件

Javascript/NodeJS 正则表达式评估在第三次尝试时失败

javascript - 使用 jQuery 动态添加删除行

javascript - 使用 *= 的 jQuery 属性选择器

javascript - 在 sibling 之间存储事件状态

javascript - 如何在 Apollo 中关闭 GraphQL 订阅的套接字连接