Как показать загрузку при смене ключа в useSWR, даже если данные для ключа уже существуют в кэше?

Вопрос или проблема

Как показать загрузку при смене ключа в useSWR, даже если данные для ключа уже существуют в кэше?

Я использую хук useSWR для получения данных. Я хочу показывать “Загрузка”, всякий раз, когда изменяется ключ. Я включил состояние filter в ключ useSWR, так что каждый раз, когда состояние обновляется, будет вызвана API.

Например, в интерфейсе, когда я нажимаю на чекбокс “Завершено” (пожалуйста, посмотрите ссылку на площадку), в первый раз значение isLoading равно true. Затем, если я снимаю отметку и снова ставлю чекбокс “Завершено”, значение isLoading становится false, потому что данные уже существуют в кэше для того же ключа.

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

Я хочу показывать “Загрузка”, всякий раз, когда пользователь применяет какой-либо фильтр. Буду признателен за любую помощь.

const [filter, setFilter] = useState({
   filterText: '',
   showCompleted: false,
});

const { data, error, isLoading, mutate } = useSWR(
    ['https://jsonplaceholder.typicode.com/todos', filter],
    async ([url, filter]) => {
        const res = await fetch(`${url}?completed=${filter.showCompleted}`);
        return await res.json();
    }
);

Площадкаhttps://stackblitz.com/edit/vitejs-vite-n8hjaa?file=src%2FApp.jsx

Ответ или решение

Для решения проблемы отображения индикатора загрузки при изменении ключа в useSWR, даже если данные уже существуют в кэше, вы можете использовать состояние для управления индикатором загрузки непосредственно при изменении фильтров. Вот несколько шагов, как это можно реализовать:

  1. Создайте локальное состояние загрузки: Используйте useState для создания состояния, которое будет контролировать, находится ли приложение в режиме загрузки.

  2. Управляйте состоянием загрузки при изменения фильтров: При каждом изменении фильтрa устанавливайте состояние загрузки в true и возвращайте его в false, когда данные загружены.

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

Ниже представлен пример кода, который иллюстрирует эти шаги:

import React, { useState, useEffect } from 'react';
import useSWR, { mutate } from 'swr';

const App = () => {
  const [filter, setFilter] = useState({
    filterText: '',
    showCompleted: false,
  });
  const [isLoading, setIsLoading] = useState(false);

  // Функция для фетчинга данных по API
  const fetcher = async (url, filter) => {
    const res = await fetch(`${url}?completed=${filter.showCompleted}`);
    if (!res.ok) {
      throw new Error('Ошибка сети');
    }
    return await res.json();
  };

  // Используем useSWR для фетчинга данных
  const { data, error, isValidating } = useSWR(
    ['https://jsonplaceholder.typicode.com/todos', filter],
    fetcher
  );

  // Эффект для обработки изменения фильтров
  useEffect(() => {
    // Устанавливаем индикатор загрузки в true при изменении фильтров
    setIsLoading(true);

    // Функция для обновления состояния после фетчинга
    const fetchData = async () => {
      await mutate(['https://jsonplaceholder.typicode.com/todos', filter]);
      setIsLoading(false); // Скрываем индикатор загрузки после получения данных
    };

    fetchData();
  }, [filter]); // Эффект вызывается при изменении filter

  // Обработка ошибок
  if (error) return <div>Ошибка загрузки: {error.message}</div>;

  // Показ индикатора загрузки
  if (isLoading || isValidating) return <div>Загрузка...</div>;

  return (
    <div>
      <h1>TODO List</h1>
      <label>
        <input
          type="checkbox"
          checked={filter.showCompleted}
          onChange={(e) => setFilter({ ...filter, showCompleted: e.target.checked })}
        />
        Показать завершённые
      </label>
      <ul>
        {data && data.map(todo => (
          <li key={todo.id}>{todo.title}</li>
        ))}
      </ul>
    </div>
  );
};

export default App;

В этом коде:

  • Мы создаем новое состояние isLoading, которое управляет отображением индикатора загрузки.
  • При изменении фильтров, индикатор загрузки активируется, и в useEffect вызывается функция fetchData, которая обрабатывает фетчинг данных и отключает индикатор загрузки после завершения процесса.
  • В компоненте также учитываются ошибки и данные загружаются из кэша, когда это возможно.

Таким образом, вы сможете показывать индикатор загрузки каждый раз, когда пользователь изменяет фильтры, независимо от того, есть ли данные в кэше.

Оцените материал
Добавить комментарий

Капча загружается...