Как использовать данные, хранящиеся в кеше, с помощью ловушек SWR и как сделать выборку SWR только один раз

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

const { data } = useSwr('same route as previous one')

и он предоставит вам данные, сохраненные в кеше предыдущим вызовом swr.


const CategoryList = ({setLoading}) => {

    const [category, setCategory] = useState('');
    const [mounted, setMounted] = useState(false);
    const [parameters, setParameters] = useState({});
    const company_id = localStorage.getItem('company_id')

    const session = new SessionService();
    const { dataFromFetch, error } = useSWR([mounted ? `${session.domain}/company/${company_id}/category-stats` : null, parameters ], url =>
      session.fetch(url, {
          method: 'GET',
      })
      , {
          onSuccess: (dataFromFetch) => {
            setCategory(dataFromFetch)
            setLoading(false)
            setMounted(false)
          },
          onError: (err, key, config) => {
            console.log("error", err)
          }
      }
  )

  useEffect(() => {
    setMounted(true)
    setLoading(true)
  }, [])

    return (
        <div className={classes.CategoryList}>
            <h5>Parc de véhicules</h5>
            <div className={classes.CategoriesCards}>
            {category.data? category.data.map((element, index) => {
                return <CategoryItem
                            category={element.data.name}
                            carNumber={element.stats.nb_vehicles}
                            locating={element.stats.nb_booked}
                            available={element.stats.nb_available}
                            blocked={element.stats.nb_unavailable}
                            percentage={(element.stats.nb_booked / element.stats.nb_vehicles * 100).toFixed(2)}
                            key={index}
                        />
            }): null}
            </div>
        </div>
    )
}

export default CategoryList;

Кроме того, с другой стороны, я бы хотел, чтобы мои перехватчики SWR не пытались постоянно обновлять данные, как если бы они были на самом деле. Я пробовал передавать параметры после моей функции извлечения, как это предусмотрено в этом сообщении с объяснением параметров SWR. На самом деле мой компонент пытается обновлять данные каждые 5-10 секунд, хотя безуспешно из-за моего "установленного" условия, которое приводит к "нулевому" маршруту (что является рекомендуемым способом сделать это в соответствии с документацией). Он по-прежнему отправляет запрос с ответом 404, чего я бы хотел избежать.

const [parameters, setParameters] = useState({
      revalidateOnFocus: false,
      revalidateOnMount:false,
      revalidateOnReconnect: false,
      refreshWhenOffline: false,
      refreshWhenHidden: false,
      refreshInterval: 0
    });
    const company_id = localStorage.getItem('company_id')

    const session = new SessionService();
    const { dataFromFetch, error } = useSWR([mounted ? `${session.domain}/company/${company_id}/category-stats` : null, parameters ], url =>
      session.fetch(url, {
          method: 'GET',
      })
      , {
          onSuccess: (dataFromFetch) => {
            setCategory(dataFromFetch)
            setLoading(false)
            setMounted(false)
          },
          onError: (err, key, config) => {
            console.log("error", err)
          }
      }
  )

1 ответ

Согласно документации SWR, API ловушки

const { data, error, isValidating, mutate } = useSWR(key, fetcher, options)

В вашем коде вы передаете параметры как часть массива в первом аргументе, тогда как он должен быть третьим.

Небольшой рефакторинг показывает, как это можно исправить:

const parameters = {
  revalidateOnFocus: false,
  revalidateOnMount: false,
  revalidateOnReconnect: false,
  refreshWhenOffline: false,
  refreshWhenHidden: false,
  refreshInterval: 0,
};

const company_id = localStorage.getItem( "company_id" );

const session = new SessionService();

const fetcher = (url) =>
  session.fetch(url, {
    method: "GET",
  });

const key = mounted
  ? `${session.domain}/company/${company_id}/category-stats`
  : null;

const { data, error } = useSWR(key, fetcher, parameters );

Вы также немного усложнили свой код - нет необходимости в onSuccess или же onError обработчики - вы можете просто использовать возвращаемые значения data и error вместо.

Кроме того, нет необходимости сохранять полученные данные в состояние с помощью setCategory. Просто читайте прямо из data. В этом преимущество SWR. Он автоматически запускает повторный рендеринг при получении данных.

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