Fetching query in method of a class component

Deadly 提交于 2020-01-16 19:49:11

问题


Apollo client (2.6.3) with react. Is it possible to fetch data in a method of a class component? I'm building a global search component and I want to fetch data only when 3rd (and each subsequent) character is typed. Right now it is implemented with fetch api but I want to switch to apollo client and graphql api.

Until this moment I haven't gotten any problems with apollo client API cause I use <Query/> component.

I've tried to use new hooks api but it turned out that useLazyQuery() can be used only in a function component (rules of hooks).

This is what I have done so far. I know that component is messy and I'm open to suggestions. This is my first react app.

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;

回答1:


Apollo Client offers a Promise-based API that provides more imperative control over when/where your queries/mutations are run. Here's an example from their docs:

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

You can import your client and use this pattern in any method or function like any other async operation using Promises.



来源:https://stackoverflow.com/questions/57874784/fetching-query-in-method-of-a-class-component

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!