简体   繁体   中英

How do I perform GraphQL Query onClick in React with Apollo?

I'm trying to filter particular Eateries based on foodType which is passed as a string eg("Chicken", "Pizza" etc).

I want to be able to do it onClick in my React component .

I've tried wrapping in an <ApolloPriver> wrapper to do a query but not had much luck.

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>
)}

The GQL query I want to pass

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

How I'm currently showing all the eateries in FoodTypes.tsx . This is where I want the results to go onClick of the buttons above.

<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>

The whole 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;

Updated 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;

What would the best approach be to get the above elements to use the GQL query above onClick?

Firstly, I would recommend you change your FoodTypes component to a React component so that you are able to store the data returned from your graphql query in state

export class classFoodTypes extends React.Component 

Now, in your classFoodTypes component, you can call setState after fetching your data:

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

From there, you can display your data from 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}
            />

I'm not going to finish implementing the rest of your component so you can practice the implementation, but this pattern should help lead you in the right direction. Let me know if you get stuck along the way.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM