Как я могу найти массив с помощью кеша React Apollo-Client? - PullRequest
0 голосов
/ 24 апреля 2020

У меня есть простой компонент поиска и функция handleSearch:

  const { data, loading, error } = useQuery(QUERY_GET_ELEMENTS);
  const client = useApolloClient();

   <input
     onChange={handleSearch}
     placeholder="&#128270;  Search..."
   />

  function handleSearch(e) {
    const { value } = e.target;

    const matchingElements = data.filter(({ name }) =>
      name.toLowerCase().includes(value.toLowerCase())
    );

    client.writeData({
      data: {
        elements: matchingElements
      }
    });
  }


  // rendering the elements looks something like this:

  data.elements.map(el => <div>{el.name}</div>

Данные поступают из ловушки useQuery.

Проблема заключается в том, что поиск работает только в одном направлении, как только элементы фильтруются Я теряю первоначальный список. Мне нужно хранить все элементы, которые я могу отфильтровать, и отобразить только отфильтрованные, сохраняя при этом исходный список.

Я использую apollo для управления состоянием и, похоже, это не работает. Моей первой мыслью было использовать client.writeData для дублирования элементов, и это никогда не будет изменено, однако это не сработало, как ожидалось.

Любая помощь очень ценится.

1 Ответ

0 голосов
/ 24 апреля 2020

Вы должны быть в состоянии выполнить sh это с помощью крюка useState. Этот пример работает для меня:

import React, { useState, useEffect } from 'react';
import gql from 'graphql-tag';
import { useQuery } from '@apollo/react-hooks'

const QUERY_GET_ELEMENTS = gql`
    {
        elements {
            id
            name
        }
    }
`;

export default function Test() {
    const [isDisplayDataSet, setIsDisplayDataSet] = useState(false);
    const [displayData, setDisplayData] = useState([]);
    const { data, loading, error } = useQuery(QUERY_GET_ELEMENTS);


    useEffect(() => {
        if (!loading && !isDisplayDataSet) {
            setDisplayData(data.elements);
            setIsDisplayDataSet(true);
        }
    }, [isDisplayDataSet, displayData, data, loading])


    function handleSearch(e) {
        const { value } = e.target;

        const matchingElements = data.elements.filter(({ name }) =>
            name.toLowerCase().includes(value.toLowerCase())
        );

        setDisplayData(matchingElements);
    }

    if (error) {
        console.error(error);
        return <h1>There was an error</h1>
    }

    if (isDisplayDataSet) {
        return (
            <>
                <input
                    className="form-control mb-3"
                    onChange={handleSearch}
                    placeholder="&#128270;  Search..."
                />

                <ul className="list-group">
                    {displayData.map(el => <li className="list-group-item" key={el.id}>{el.name}</li>)}
                </ul>
            </>
        );
    } else {
        return '';
    }
}

Я добавил несколько bootstrap классов для стилизации:)

А вот быстрый и грязный сервер apollo, который я настроил для загрузки некоторых данных в:

const { ApolloServer } = require('apollo-server');
const gql = require('graphql-tag');
const fetch = require('node-fetch');

const typeDefs = gql`
    type Element {
        id: ID!
        name: String!
    }

    type Query {
        elements: [Element]!
    }

    schema {
        query: Query
    }
`;

const resolvers = {
    Query: {
        async elements() {
            const res = await fetch('https://reqres.in/api/users');
            const { data } = await res.json();

            const elements = data.map(({ id, first_name, last_name }) => ({ id, name: `${first_name} ${last_name}` }))

            console.log('elements', elements);

            return elements;
        }
    }
}

const server = new ApolloServer({
    typeDefs,
    resolvers
});

server.listen().then(({ url }) => {
    console.log('server ready on ' + url);
});
...