【问题标题】:How do I perform GraphQL Query onClick in React with Apollo?如何在 React with Apollo 中执行 GraphQL Query onClick?
【发布时间】:2019-12-05 20:09:21
【问题描述】:

我正在尝试根据foodType 过滤特定的Eateries,该foodType 作为字符串 例如(“Chicken”、“Pizza”等)传递。

我希望能够在我的 React 组件中做到这一点onClick

我尝试使用 <ApolloPriver> 包装器进行查询,但运气不佳。

FoodType.tsx

export const FoodTypes: React.SFC = () => {
  return (
    <div className="food-types">
      <ul className="food-type-list">
        <li className="food-type-item" onClick={async () => {
                const { data } = await client.query({
                  query: FOODTYPE_QUERY,
                  variables: { foodType: "Pizza" }
                })}}>Pizza</li>
        <li className="food-type-item" onClick={}>Chicken</li>
        <li className="food-type-item" onClick={}>Indian</li>
        <li className="food-type-item" onClick={}>Chinese</li>
        <li className="food-type-item" onClick={}>English</li>
        <li className="food-type-item" onClick={}>Fish & Chips</li>
        <li className="food-type-item" onClick={}>Kebab</li>
        <li className="food-type-item" onClick={}>Curry</li>
        <li className="food-type-item" onClick={}>Caribbean</li>
      </ul>
)}

我要传递的 GQL 查询

const FOODTYPE_QUERY = gql`
  query foodTypeQuery($foodType: String!) {
    getFoodType(foodType: $foodType) {
      id
      name
      address
      foodType
    }
  }
`;

我目前如何展示FoodTypes.tsx 中的所有餐厅。这是我希望结果转到上面按钮的onClick 的地方。

<div className={"EateryWrapper"}>
        <ApolloProvider client={client}>
          <Query query={EATERY_QUERY}>
            {({ loading, data }: any) => {
              if (loading) return "Loading...";
              const { eateries } = data;
              return eateries.map((eatery: any) => (
                <EateryItem
                  key={eatery.id}
                  id={eatery.id}
                  name={eatery.name}
                  address={eatery.address}
                  foodType={eatery.foodType}
                />
              ));
            }}
          </Query>
        </ApolloProvider>
      </div>

整个FoodTypes.tsx

import React from "react";
import "./FoodTypes.scss";
import { ApolloProvider, Query } from "react-apollo";
import { gql } from "apollo-boost";

import { client } from "../..";
import { EateryItem } from "../Eatery/EateryItem";

const EATERY_QUERY = gql`
  {
    eateries {
      id
      name
      address
      foodType
    }
  }
`;

const FOODTYPE_QUERY = gql`
  query foodTypeQuery($foodType: String!) {
    getFoodType(foodType: $foodType) {
      id
      name
      address
      foodType
    }
  }
`;

export const FoodTypes: React.SFC = () => {
  return (
    <div className="food-types">
      <ul className="food-type-list">
        <li className="food-type-item" onClick={async () => {
          const { data } = await client.query({
            query: FOODTYPE_QUERY,
            variables: { foodType: "Pizza" }
          })
          console.log(data)}
        }>Pizza</li>
        <li className="food-type-item">Chicken</li>
        <li className="food-type-item">Indian</li>
        <li className="food-type-item">Chinese</li>
        <li className="food-type-item">English</li>
        <li className="food-type-item">Fish & Chips</li>
        <li className="food-type-item">Kebab</li>
        <li className="food-type-item">Curry</li>
        <li className="food-type-item">Caribbean</li>
      </ul>
      <div className={"EateryWrapper"}>
        <ApolloProvider client={client}>
          <Query query={EATERY_QUERY}>
            {({ loading, data }: any) => {
              if (loading) return "Loading...";
              const { eateries } = data;
              return eateries.map((eatery: any) => (
                <EateryItem
                  key={eatery.id}
                  id={eatery.id}
                  name={eatery.name}
                  address={eatery.address}
                  foodType={eatery.foodType}
                />
              ));
            }}
          </Query>
        </ApolloProvider>
      </div>
    </div>
  );
};

export default FoodTypes;

更新FoodTypes.tsx

import React, { Component, useState } from "react";
import "./FoodTypes.scss";
import { ApolloProvider, Query } from "react-apollo";
import { gql } from "apollo-boost";

import { client } from "../..";
import { EateryItem } from "../Eatery/EateryItem";

const EATERY_QUERY = gql`
  {
    eateries {
      id
      name
      address
      foodType
    }
  }
`;

const FOODTYPE_QUERY = gql`
  query foodTypeQuery($foodType: String!) {
    getFoodType(foodType: $foodType) {
      id
      name
      address
      foodType
    }
  }
`;

type foodTypeFilterProps = {
  foodTypeName: String
}

export const FoodTypes: React.SFC = () => {
  return (
    <div className="food-types">
      <ul className="food-type-list">
        <FoodTypeFilter foodTypeName={'Italian'}/>
        <FoodTypeFilter foodTypeName={'Pizza'}/>
        <FoodTypeFilter foodTypeName={'Chicken'}/>
        <FoodTypeFilter foodTypeName={'Indian'}/>
        <FoodTypeFilter foodTypeName={'Chinese'}/>
        <FoodTypeFilter foodTypeName={'English'}/>
        <FoodTypeFilter foodTypeName={'Fish & Chips'}/>
        <FoodTypeFilter foodTypeName={'Kebab'}/>
        <FoodTypeFilter foodTypeName={'Curry'}/>
        <FoodTypeFilter foodTypeName={'Caribbean'}/>
      </ul>
      <div className={"EateryWrapper"}>
        <ApolloProvider client={client}>
          <Query query={EATERY_QUERY}>
            {({ loading, data }: any) => {
              if (loading) return "Loading...";
              const { eateries } = data;
              return eateries.map((eatery: any) => (
                <EateryItem
                  key={eatery.id}
                  id={eatery.id}
                  name={eatery.name}
                  address={eatery.address}
                  foodType={eatery.foodType}
                />
                ));
            }}
          </Query>
        </ApolloProvider>
      </div>
    </div>
  );
};

const FoodTypeFilter: React.FunctionComponent<foodTypeFilterProps> = props => {
  const [foodType, setFoodType] = useState(props.foodTypeName);
  return(
    <li className="food-type-item" onClick={async () => {
      const { data } = await client.query({
        query: FOODTYPE_QUERY,
        variables: { foodType: props.foodTypeName }
      })
      setFoodType(foodType);
      }}>{foodType}
      </li>
  )
}

export default FoodTypes;

让上述元素使用 onClick 上方的 GQL 查询的最佳方法是什么?

【问题讨论】:

  • 您的 onClick 功能目前是什么样的?你试过什么?
  • 嘿@Jim 我已经用我迄今为止尝试过的 onClick 更新了上面的例子:)
  • 是否有任何控制台错误或正在发送任何网络请求?
  • 因此,当您在pizza 上单击时,查询应该会触发并将结果分配给data。您希望如何处理结果 (data)?
  • 谢谢@Jim 我实际上是从 GQL 返回了包含正确信息的正确数组,但我现在想显示我当前显示所有 eateries 的数据。更新了原始问题以显示我想要数据显示的位置:)

标签: javascript reactjs typescript graphql apollo


【解决方案1】:

首先,我建议您将 FoodTypes 组件更改为 React 组件,以便您能够将从您的 graphql 查询返回的数据存储在 state

export class classFoodTypes extends React.Component 

现在,在您的classFoodTypes 组件中,您可以在获取数据后调用setState

<li className="food-type-item" onClick={async () => {
                const { data } = await client.query({
                  query: FOODTYPE_QUERY,
                  variables: { foodType: "Pizza" }
                })}
                this.setState({eateries: data})}>Pizza</li>

从那里,您可以显示来自state 的数据:

            <EateryItem
              key={this.state.eateries.id}
              id={this.state.eateries.id}
              name={this.state.eateries.name}
              address={this.state.eateries.address}
              foodType={this.state.eateries.foodType}
            />

我不会完成您组件的其余部分的实现,因此您可以练习实现,但是这种模式应该可以帮助您朝着正确的方向前进。如果您在途中遇到困难,请告诉我。

【讨论】:

  • 这太棒了@Jim,几乎让我到了那里。我必须使用钩子而不是类,因为我使用钩子作为主要组件。不确定我是否可以像您提到的那样扩展它?虽然现在真正的问题是从我在底部添加的新FoodTypeFilter 钩子中的useState() 钩子访问状态。我想将它传递给 EateryItem 组件以进行映射以显示当前的 Eateries 集。
猜你喜欢
  • 2021-06-09
  • 2017-11-30
  • 1970-01-01
  • 1970-01-01
  • 2016-11-30
  • 2017-02-10
  • 1970-01-01
  • 2023-03-22
相关资源
最近更新 更多