React useEffect выполняется условно

#reactjs #react-redux #react-hooks #use-effect #react-effects

#reactjs #react-redux #реагирующие хуки #использование-эффект #реакция-эффекты

Вопрос:

Как мне запретить моему компоненту React извлекать изображения каждый раз, когда компонент отображается, и вместо этого извлекать их из хранилища? Я не хочу ограничивать скорость, выполняя вызов API снова и снова, но проблема в useEffect том, что он, похоже, не знает о переменных, устанавливаемых «вне» эффекта. Кажется, что он полностью игнорируется !images.length , и когда я регистрирую значение для images.length него всегда 0 🙁

Images.tsx

 const dispatch = useDispatch();
const images = useSelector(selectedImages);

useEffect(() => {
  if (!images.length) {
    dispatch(fetchImages());
  }
}, []);
  

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

1. вы можете поддерживать флаг, localStorage чтобы проверить это

2. Images должно быть в массиве зависимостей вашего useEffect. Второй аргумент в вашем useEffect должен быть [images]

3. @johnnypeter не будет ли это перерисовываться каждый раз images , когда длина будет меняться?

4. Да, это будет срабатывать каждый раз, когда изменяется длина. Чтобы избежать извлечения уже выбранного изображения, вы можете поддерживать и использовать внутренний кеш, чтобы сохранить то, что уже загружено, и пропустить их.

Ответ №1:

С помощью React hook useMemo вы будете вызывать API только тогда, когда вам это нужно

https://www.robinwieruch.de/react-usememo-hook

https://reactjs.org/docs/hooks-reference.html#usememo

Ответ №2:

Это всегда ведение 0 журнала, потому что вы ничего не помещали в массив зависимостей useEffect , так что всякий раз, когда React повторно отображает ваш компонент, он заглядывает внутрь useEffect и ничего не видит внутри массива dep, поэтому он просто пропускает его запуск useEffect .

При использовании вы useEffect должны объявлять зависимости в массиве useEffect , которые используются внутри useEffect

 const dispatch = useDispatch();
const images = useSelector(selectedImages);

useEffect(() => {
  if (!images.length) {
    dispatch(fetchImages());
  }
}, [images]); // Our deps
  

Итак, допустим:

  1. Во-первых, по умолчанию он будет запускать useEffect и выполнять всю логику внутри этого эффекта. Если массив изображений пуст, вызов API для получения изображений.
  2. Во-вторых, images массив больше не пуст, а 2-й images отличается от 1-го images массива, который является пустым, поэтому он все равно выполняется до useEffect . Но он больше не будет извлекать изображения, потому что у вас if condition есть.