Окно поиска с React-запросом

#javascript #reactjs #next.js #react-query

Вопрос:

Я пытаюсь реализовать поиск товаров по text . Получение данных с react-query помощью . Следующая реализация работает, но мне кажется, что это неправильно. Дайте мне знать, если я переусердствую и если есть более простое решение react-query .

 import { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import { useQueryClient } from 'react-query';
import ProductCard from '@/components/cards/ProductCard';
import { useQueryProducts } from '@/hooks/query/product';
import { selectSearch } from '@/store/search';

// function fetchProductsByFilter(text){}

const Shop = ({ count }) => {
  const [products, setProducts] = useState([]);
  const [loading, setLoading] = useState(true);

  const { text } = useSelector(selectSearch);

  const productsQuery = useQueryProducts(count);

  useEffect(() => {
    setProducts(productsQuery.data);
    setLoading(false);
  }, []);

  const queryClient = useQueryClient();

  useEffect(() => {
    const delayed = setTimeout(() => {
      queryClient.prefetchQuery(['searchProductsByText'], async () => {
        if (text) {
          const data = await fetchProductsByFilter(text);
          setProducts(data);
          setLoading(false);
          return data;
        }
      });
    }, 300);
    return () => clearTimeout(delayed);
  }, [text]);

  return (
    <div className="container-fluid">
      <div className="row">
        <div className="col-md-3">search/filter menu</div>

        <div className="col-md-9">
          {loading ? (
            <h4 className="text-danger">Loading...</h4>
          ) : (
            <h4 className="text-danger">Products</h4>
          )}

          {products.length < 1 amp;amp; <p>No products found</p>}

          <div className="row pb-5">
            {products.map((item) => (
              <div key={item._id} className="col-md-4 mt-3">
                <ProductCard product={item} />
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
};

// async function getServerSideProps(context) {}

export default Shop;
 

Ответ №1:

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

Если это происходит при выборе чего-либо из списка «Выбрать» или нажатии кнопки «Применить», это действительно все, что вам нужно:

 const [filter, setFilter] = React.useState(undefined)
const { data, isLoading } = useQuery(
  ['products', filter], 
  () => fetchProducts(filter)
  { enabled: Boolean(filter) }
)
 

Здесь я дополнительно отключаю запрос до тех пор, пока есть фильтр undefined — выборка начнется, как только мы вызовем setFilter .


если требуется ввести текст в текстовое поле, я бы рекомендовал немного отменить, чтобы избежать слишком большого количества запросов. Используемый крючок для прыжка очень хорош для этого. У вас все равно будет useState , но вы будете использовать отмененное значение для запроса:

 const [filter, setFilter] = React.useState(undefined)
const debouncedFilter = useDebounce(filter, 500);
const { data, isLoading } = useQuery(
  ['products', debouncedFilter], 
  () => fetchProducts(debouncedFilter)
  { enabled: Boolean(debouncedFilter) }
)
 

Комментарии:

1. вау, это так круто. Спасибо!!! Многому у тебя учусь.