在类组件的方法中获取查询 [英] Fetching query in method of a class component

查看:21
本文介绍了在类组件的方法中获取查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

我尝试使用新的 hooks api,但结果是 useLazyQuery() 只能在函数组件中使用(钩子规则).

这是我目前所做的.我知道这个组件很乱,我愿意接受建议.这是我的第一个反应应用.

import React, { Component } from "react";从prop-types"导入 PropTypes;import { Select, Icon, Button } from "antd";从../../../utils/queries"导入{es};从@apollo/react-hooks"导入 { useLazyQuery };const { 选项,OptGroup } = 选择;类 GlobalSearch 扩展组件 {构造函数(道具){超级(道具);this.searchInput = React.createRef();}状态 = {数据: [],值:未定义,显示:假};componentDidMount() {document.addEventListener("click", this.onClickOutside);}生成选项(数据){返回 data.map(d => {if (d._index === "cases") {d.标签=(<div><图标样式={{ fontSize: "18px" }} type="tool"/><span style={{ color: "#183247" }}>{d._source.number + d._source.serialNumber}</span>

);} else if (d._index === "items") {d.标签=(<div><图标样式={{ fontSize: "18px" }} type="barcode-o"/><span style={{ color: "#183247" }}>{d._source.name}</span>

);} else if (d._index === "人") {d.标签=(<div><图标类型=用户"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>

);} else if (d._index === "对方") {d.标签=(<div><图标样式={{ fontSize: "18px" }} type="shop"/><span style={{ color: "#183247" }}>{d._source.name}</span>

);} 别的 {d.label = "未定义";}返回d;});}//根据搜索结果的类型对数据进行分组(索引例如案例、项目、联系人)setData = es_data =>{常量数据 = {};const map = new Map();for (es_data 的常量项) {如果 (!map.has(item._index)) {map.set(item._index);数据[item._index] = [];}数据[item._index].push(item);}this.setState({数据:数据});};handleSearch = 值 =>{if (value.length > 2) {//tutaj wyszukujemy dane na serwerze a wyniki callbackiem przesyłamy do state.data[]//response.json() 从 body 调用 mixin 方法const 主机 = window.location.hostname//const { loading, data } = useLazyQuery(es(value));//if (loading) return undefined;//如果(数据){//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 = 值 =>{//przy kazdym wpisanym znaku aktualizuj wartosc polathis.setState({值});};handleSelect = (key, option) =>{控制台日志(键);控制台日志(选项);};handleBlur = e =>{this.setState({ display: false, value: undefined, data: [] });};onClick = () =>{this.setState({ display: !this.state.display });};getSearchField(选项){如果(this.state.display){返回 (<选择id="全局搜索字段"optionLabelProp="标签"显示搜索值={this.state.value}placeholder="搜索..."}style={{ display: this.state.display, width: "350px" }}defaultActiveFirstOption={true}显示箭头={假}filterOption={false}onSearch={this.handleSearch}onChange={this.handleChange}onSelect={this.handleSelect}notFoundContent={"这里什么都没有..."}onBlur={this.handleBlur}自动对焦={真}showAction={["焦点"]}dropdownClassName="全局搜索下拉">{选项});}}使成为() {//为每个组生成选项(索引)const options = Object.keys(this.state.data).map(d => (<OptGroup 标签={d}>{this.state.data[d].map(d => (<选项类名={d._index}类型={d._index}键={d._id}标签={d.label}><div>{d.label}</div></选项>))}</OptGroup>));返回 (<跨度>{this.getSearchField(options)}<按钮id="全局搜索"形状=圆圈"图标=搜索"onClick={this.onClick}/></span>);}}导出默认全局搜索;

解决方案

Apollo Client 提供了一个基于 Promise 的 API,可以对查询/突变运行的时间/地点提供更多命令式控制.以下是他们的文档中的示例:>

客户端.询问({查询:gql`查询获取启动{启动(ID:56){ID使命 {姓名}}}`,变量:{ ... }}).then(result => console.log(result));

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

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;

解决方案

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.

这篇关于在类组件的方法中获取查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆