Как выполнить запрос GraphQL onClick в React с помощью Apollo?

Я пытаюсь отфильтровать конкретный Закусочные на основе foodType, который передается как нить, например («Курица», «Пицца» и т. д.).

Я хочу иметь возможность сделать это 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.info(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;

Каков наилучший подход, чтобы заставить вышеуказанные элементы использовать запрос GQL выше onClick?

Как сейчас выглядит ваша функция onClick? Что вы пробовали?

Magnum 28.07.2019 07:34

Привет, @Jim, я обновил приведенный выше пример тем, что я пробовал до сих пор с onClick :)

Harry 28.07.2019 13:08

Есть ли какая-либо ошибка консоли или отправляется какой-либо сетевой запрос?

Pedram marandi 28.07.2019 16:22

Таким образом, с вашим onClick на pizza запрос должен сработать и присвоить результат data. Что вы хотите сделать с результатом (data)?

Magnum 28.07.2019 18:34

Спасибо @Jim. На самом деле я возвращаю правильный массив с правильной информацией из GQL, но теперь я хотел показать данные там, где я сейчас показываю все eateries. Обновлен исходный вопрос, чтобы показать, где я хотел показать данные :)

Harry 28.07.2019 18:57
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
5
865
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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, что почти довел меня до цели. Мне пришлось использовать хук вместо класса, так как я использую хуки в качестве основного компонента. Не уверен, смогу ли я расширить его, как вы упомянули? Хотя реальная проблема теперь заключается в доступе к состоянию из хука useState() в новом хуке FoodTypeFilter, который я добавил внизу. Я хочу передать его в компонент EateryItem, чтобы отображать текущий набор закусочных.

Harry 28.07.2019 23:46

Другие вопросы по теме