React: У React Hook useEffect отсутствует зависимость: 'xxx'?

Созданный на 12 июн. 2019  ·  69Комментарии  ·  Источник: facebook/react

Привет, я недавно изучаю React Hook, это здорово.

Но у меня проблема, я не нашел подходящего ответа в документации React Hook и гугле для решения своей проблемы.

Когда я использовал функцию в useEffect и функциональный компонент вместе, я обнаружил предупреждение о том, что я не указал зависимость в useEffect, как показано ниже:

image

Есть ли способ решить мою проблему? Я долго думал об этом.

Каково текущее поведение?

React Hook useEffect has a missing dependency: 'setCenterPosition'. Either include it or remove the dependency array. (react-hooks/exhaustive-deps)

Мини-репродукция в Codeandbox:
https://codesandbox.io/s/trusting-kowalevski-oet4b

Любое решение, спасибо.

Код

function App() {
  const [elePositionArr, setElePositionArr] = useState([
    { left: 0, top: 0 },
    { left: 0, top: 0 },
    { left: 0, top: 0 }
  ]);
  const stageRef = useRef(null);
  const Stage = useRef({ w: 0, h: 0 });
  const currentIndex = useRef(0);

  useEffect(() => {
    // Record the size of the stage
    const stageW = stageRef.current.scrollWidth;
    const stageH = stageRef.current.scrollHeight;

    Stage.current = { w: stageW, h: stageH };

    const index = Math.floor(Math.random() * 3);
    currentIndex.current = index;
    setCenterPosition(index);
  }, []);

  // Centering a block element
  function setCenterPosition(index) {
    let cacheEle = elePositionArr;
    // calc center postion
    const centerOfLeft = Stage.current.w / 2 - 25;
    const centerOfTop = Stage.current.h / 2 - 25;

    cacheEle = cacheEle.map((item, i) => {
      const randomWNum = Math.floor(Math.random() * Stage.current.w) - 50;
      const randomHNum = Math.floor(Math.random() * Stage.current.h) - 50;
      const randomLeft = randomWNum <= 50 ? 50 : randomWNum;
      const randomTop = randomHNum <= 50 ? 50 : randomHNum;
      let newItem;

      if (index === i) {
        newItem = { left: centerOfLeft, top: centerOfTop };
      } else {
        newItem = { left: randomLeft, top: randomTop };
      }

      return newItem;
    });

    setElePositionArr(cacheEle);
  }

  function handleClickLi(index) {
    if (currentIndex.current !== index) {
      setCenterPosition(index);
      currentIndex.current = index;
    }
  }

  return (
    <div className="container">
      <div className="stage" ref={stageRef}>
        {elePositionArr.map((item, index) => (
          <div className="ele" key={index} style={item}>
            {index}
          </div>
        ))}
      </div>
      <ul className="nav">
        {elePositionArr.map((item, index) => (
          <li
            className={currentIndex.current === index ? "active-li" : ""}
            onClick={() => {
              handleClickLi(index);
            }}
            key={"li" + index}
          >
            {index}
          </li>
        ))}
      </ul>
    </div>
  );
}

Самый полезный комментарий

Когда тысячи разработчиков сталкиваются с этой же проблемой, а команда разработчиков React закрывает обсуждение и игнорирует всех:
8d6

Все 69 Комментарий

Это должно ответить на ваш вопрос:

https://reactjs.org/docs/hooks-faq.html#is -it-safe-to-omit-functions-from-the-list-of-dependencies

Это должно ответить на ваш вопрос:

https://reactjs.org/docs/hooks-faq.html#is -it-safe-to-omit-functions-from-the-list-of-dependencies

@gaearon
Не решил мою проблему, моя проблема более особенная, моя функция запуска setElePositionArr хочет срабатывать на componentDidMount и handleClick, но функция React Hook не соответствует моим требованиям, и появляется предупреждение.

Мой вопрос: React Hook не может вызвать функцию в useEffect и функциональном компоненте для операции setState?

Оставляем открытым, чтобы мы могли ответить на второй вопрос.

У меня такое же предупреждение ESLint, но в моем случае я хочу сделать асинхронный вызов, когда мой компонент установлен.

const ManageTagsModalBody: React.FC<IProps> = ({ children, getTags }) => {
  useEffect(() => {
    getTags();
  }, []);

  return <div>{children}</div>;
};
Line 12:  React Hook useEffect has a missing dependency: 'getTags'. Either include it or remove the dependency array. If 'getTags' changes too often, find the parent component that defines it and wrap that definition in useCallback  react-hooks/exhaustive-deps 

ManageTagsModalBody не зависит от каких-либо данных, он используется только как оболочка для загрузки данных в любое время при рендеринге компонента. Стоит отметить, что компонент children использует данные, полученные getTags .

Я не уверен, что добавить в список зависимостей.

Я также заинтересован в объяснении.
У React Hook useEffect отсутствует зависимость: 'dispatch'.

  useEffect(() => {
    axios.get('http://localhost:8000/api/future-registrations')
      .then((result) => {
        dispatch(initRegistrationsAction(result.data));
      });
  }, []);

Здесь та же проблема. Странное правило.

То же самое. Так же просто, как в https://github.com/facebook/react/issues/15865#issuecomment -506503377:

  useEffect(() => {
    dispatch(fetchPosts());
  }, []);

Есть ли способ подавить это предупреждение?

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

const initFetch = useCallback(() => {
    dispatch(fetchPosts());
  }, [dispatch]);

  useEffect(() => {
    initFetch();
  }, [initFetch]);

@fayway, тогда при изменении значения initFetch и dispatch будет выполнен обратный вызов useEffect.
он хочет выполнить обратный вызов один раз

@shkyung В моем случае, initFetch не изменит причин (магазин.) отправка не либо

Может быть, это может быть так

const setCenterPosition = useRef(null)
setCenterPosition.current = useCallback( ()=>{} ,[deps])

effect(()=>{ setCenterPosition.current() },[setCenterPosition,otherDeps])

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

Есть такая же проблема. Я хочу, чтобы моя выборка запускалась только на componentDidMount. Добавление зависимости к массиву приводит к многократному попаданию в конечную точку.

У React Hook useEffect отсутствует зависимость: 'dispatch'.

const [state, dispatch] = useReducer(reducer, initialState);
const { count, step } = state;

useEffect(() => {
  const id = setInterval(() => {
    dispatch({ type: 'tick' }); // Instead of setCount(c => c + step);
  }, 1000);
  return () => clearInterval(id);
}, [dispatch]);

Это довольно распространенный вариант использования, с которым я столкнулся в своем текущем проекте.

Вы хотите запустить ловушку эффекта только один раз, но есть зависимость, хотя вы заботитесь только о ее состоянии при запуске. В настоящее время используется
// eslint-disable-next-line react-hooks/exhaustive-deps ,
чтобы отключить правило линтинга, но в этом случае было бы неплохо.

Это довольно распространенный вариант использования, с которым я столкнулся в своем текущем проекте.

Вы хотите запустить ловушку эффекта только один раз, но есть зависимость, хотя вы заботитесь только о ее состоянии при запуске. В настоящее время используется
// eslint-disable-next-line react-hooks/exhaustive-deps ,
чтобы отключить правило линтинга, но в этом случае было бы неплохо.

Закрытие Lint - это всего лишь временное решение, ключа к этой проблеме недостаточно, чтобы понять крючок.

Здесь та же проблема. Я просто хотел один раз запустить функцию внутри useEffect (), имея [] в качестве второго параметра, делает то, что я хочу, но он продолжает выдавать это предупреждение.

Такое странное предупреждение, потому что я никогда не видел его до сегодняшнего дня в новом проекте. Это разрушает вариант использования, когда что-то вызывается только один раз, когда компонент смонтирован. Кажется, нет никакого обходного пути, кроме игнорирования предупреждения о ворсинах.

Я хотел бы положить сюда свои два цента. В частности, с использованием Axios для отмены сетевого запроса. При необходимости создам отдельную проблему, но я чувствовал, что эта проблема напрямую затрагивает меня. Итак, мой хук useApi выглядит следующим образом:

import axios, { AxiosInstance } from "axios";
import axiosRetry from "axios-retry";
import { FetchEnv } from "../../utilities";
import { useStorage } from "../useStorage";

export const useApi = ({ isAuth = false, retries = 3 } = {}) => {
  const cancelToken = axios.CancelToken.source();
  const { getItem } = useStorage();

  const getBaseUrl = () => {
    return FetchEnv({
      defaultValue: "http://api.example.com",
      key: "API_URI"
    });
  };

  const authorizedClient = (client: AxiosInstance) => {
    const session = getItem("SESSION", "sessionStorage");
    const hasAccessToken = Boolean(session.tokens.accessToken);

    if (isAuth && !hasAccessToken) {
      console.error("No access token found to initiate authorized request.");
      return client;
    } else {
      client.defaults.headers[
        "Authorization"
      ] = `Bearer ${session.tokens.accessToken}`;
      return client;
    }
  };

  const buildFetch = (): AxiosInstance => {
    const client = axios.create({
      baseURL: getBaseUrl(),
      cancelToken: cancelToken.token
    });
    axiosRetry(client, { retries });
    return isAuth ? authorizedClient(client) : client;
  };

  return {
    cancelRequest: cancelToken.cancel,
    fetch: buildFetch()
  };
};

Чтобы использовать этот хук в компоненте, просто определите его, как показано ниже, после чего его можно использовать для выполнения как аутентифицированных, так и неаутентифицированных вызовов либо при монтировании, внутри useEffect, как часть обработчика событий и т. Д. CancelRequest - это уникальный сгенерированный токен отмены который связан с экземпляром axios "выборки" относительно этого компонента.

const { cancelRequest, fetch } = useApi();

Если по какой-либо причине этот компонент отключается, вызывается следующее:

  useEffect(() => {
    return () => {
      cancelRequest("Auth network request cancelled");
    };
  }, []);

Теперь он отлично работает в настоящее время. Однако предупреждение, когда оно применяется (помещая cancelRequest в качестве зависимости useEffect), немедленно ОТМЕНЯЕТ сетевой запрос при вызове метода выборки. Мы будем очень благодарны за любые советы, однако, похоже, единственное решение в настоящее время - отключить ts-lint это движение вперед ...

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

Это привело меня к Интересно , если в @ Stoner609 «s пример чуть выше этого, код синхронизации должен быть в useCallback крючок? Тем не менее, все еще странно иметь функцию (которая должна быть статической) в качестве зависимости.

Думаю, этот случай должен быть каким-то исключением

Если вы хотите запустить функцию только один раз, когда компонент загружается и принимает параметры, вы можете использовать useRef, чтобы избежать предупреждения. Примерно так работает:

  const InitialPropA= useRef(propA);
  useEffect(() => {
    myFunction(InitialPropA.current);
  }, [myFunction, InitialPropA]);

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

const initFetch = useCallback(() => {
    dispatch(fetchPosts());
  }, [dispatch]);

  useEffect(() => {
    initFetch();
  }, [initFetch]);

Как бы мне ни нравился этот остроумный ответ, обычно это то, что происходит в моем коде.
Я не хочу, чтобы все эти надоедливые предупреждения о пропаже отправлялись.

Я хотел бы точно знать, что и почему происходит в этом массиве тайн :)

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

const initFetch = useCallback(() => {
    dispatch(fetchPosts());
  }, [dispatch]);

  useEffect(() => {
    initFetch();
  }, [initFetch]);

это также может вызвать утечку памяти в случае чего-то вроде API, это вызовет бесконечный цикл.

На самом деле нужно исправить это. Он продолжает выдавать мне ошибки и не дает никаких идей, как их решить, если вы хотите запустить функцию внутри useEffect() только один раз.

Столкнувшись с той же ошибкой -

У React Hook useEffect отсутствует зависимость: props. Однако props изменится при изменении любого свойства, поэтому предпочтительным исправлением является деструктуризация объекта props вне вызова useEffect и ссылка на эти конкретные свойства внутри useEffect react-hooks / excustive-deps

Код -

  useEffect(() => {
    props.dispatch(searchMediaAction("rain"));
  }, []);

@luojinghui : Сообщите мне, если вы

та же ошибка

та же проблема. Я хочу имитировать поведение componentDidMount; Меня не интересует предупреждение; Я не хочу повторно запускать ловушку, когда что-то изменится

Я предлагаю не показывать это предупреждение, когда второй аргумент useEffect() равен [] , b / c, в этом случае разработчик знает, что этот эффект будет запускаться только один раз и поэтому _ хочет_ использовать исходные значения prop и не заботятся о том, изменится ли свойство при последующих рендерингах.

Дело 1:
Если мы хотим, чтобы функция запускалась при инициализации, а также при изменении значения указанных параметров (как предполагает предупреждение о линтах), мы передаем эти параметры в массив.

Случай 2:
Если мы хотим, чтобы функция запускалась ровно один раз при инициализации , мы используем пустой массив, чтобы эффект запускался только один раз.

В случае 2 мы, по сути, прослушиваем событие componentDidMount в соответствии со спецификациями документации React Hook. Ошибка lint несовместима с документацией React Hook и ожиданиями разработчиков.

Почему это закрыто?

Какие-нибудь решения?

@kennylbj

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

`` javascript
// ... внутри функционального компонента
const {dispatchFunc} = customHook ();
const memoizeDispatchFunc = useCallback (dispatchFunc, []);

useEffect (() => {
memoizeDispatchFunc ();
}, [memoizeDispatchFunc]);
`` ''

Можем ли мы просто удалить пустой массив? Кажется, это работает (код по-прежнему работает, как ожидалось, и предупреждение исчезло), но я не знаю, есть ли причина, по которой мы не должны делать это таким образом.

useEffect(()=>{ myFunc(); } )

@robthedev Отличное решение.
Мы даже можем упростить код, если воспользуемся redux:

const dispatch = useDispatch();

// redux can guarantee that the dispatch function will not change between renders.
// so we don't need to wrap it with useCallback for now.
useEffect(() => {
  dispatch(actions());
}, [dispatch]);

Эта статья Дэна мне очень помогает.

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

@kennylbj

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

// ... inside function component
const { dispatchFunc } = customHook();
const memoizeDispatchFunc = useCallback(dispatchFunc, []);

useEffect(() => {
  memoizeDispatchFunc();
}, [memoizeDispatchFunc]);

Со мной приведенный выше пример не работает.

Получите эту ошибку:
TypeError: Cannot destructure property 'dispatchFunc' of 'componentDidMount(...)' as it is undefined.

@ react-team: Счастливый шаблонный код. :) Может быть, это снова будет логичным и читаемым ... события должны быть простыми в использовании ... без необходимости писать 5+ строк логики только для вызова функции.

Для меня ошибка возникла в следующей ситуации:

  useEffect(() => {
    props.getTasks()
  }, [])

Исправил вот так:

const { getTasks } = props
  useEffect(() => {
    getTasks()
  }, [getTasks])

Когда тысячи разработчиков сталкиваются с этой же проблемой, а команда разработчиков React закрывает обсуждение и игнорирует всех:
8d6

моя проблема отличалась от других в этой ветке, поэтому я поделюсь ею, если какая-то другая бедняжка упадет в кроличью нору, я только что просидел 1,5 часа

function hydrate( _state, _errors=false) {
    console.log('hydrate()');
    setState({...state,..._state});
    if(_errors){
        setErrors({...errors,..._errors});
    }
}

ожидается, что пользователь будет использовать это с useEffect() , чтобы гидратировать свое состояние следующим образом:

useEffect(()=>{
    hydrate({
        name:'Garrett',
        email:'[email protected]',
        newsletter: 'yes'
    });
},[hydrate]); //unfortunately, this causes an infinite render, because hydrate will always change

поэтому, чтобы решить эту проблему, я просто изменил свою функцию гидратации, чтобы она была обернута в useCallback() , теперь она не мутирует при каждом рендеринге (я думаю), и, предположительно, это лучше для производительности, что, если это окажется правдой, я будет реализовывать это для всех моих вспомогательных функций, возвращаемых из моего настраиваемого хука.

const hydrate = useCallback(( _state, _errors=false )=> {
    console.log('hydrate()');
    setState({...state,..._state});
    if(_errors){
        setErrors({...errors,..._errors});
    }
},[]);

может ли кто-нибудь подтвердить, что это правда, useCallback предотвращает мутацию hydrate при рендеринге, и поэтому, вероятно, лучше обернуть все такие функции в useCallback для лучшей производительности ?

redux can guarantee that the dispatch function will not change between renders.

Вы уверены, что?
Ссылка на документы, где так написано, пожалуйста.

Проверьте https://overrected.io/a-complete-guide-to-useeffect/#decoupling -updates-from-actions для получения более подробной информации, или вы можете проверить исходный код useEffect для деталей реализации.

Здесь я просто ссылаюсь на то, что сказал Дэн:

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

гарантирует, что функция диспетчеризации будет постоянной

Хорошо, спасибо!

Когда тысячи разработчиков сталкиваются с этой же проблемой, а команда разработчиков React закрывает обсуждение и игнорирует всех:
8d6

Примерно так. Здесь я пробую ловушки, и меня встречает это предупреждение, которое не имеет смысла и не рассматривается ни в одной из официальных документов. Действительно заставляет задуматься, готовы ли хуки для серьезной работы, когда такой базовый вариант использования, как «пожалуйста, запустите этот эффект только один раз», дает столько проблем.

Ну, больше нечего сказать, кроме того факта, что поток закрыт smh.

Сталкивается с той же проблемой!

РЕШЕНИЕ,
(это сработало для меня):

const onInit = function(){ 
    console.log('initiated', Date.now());
}

useEffect(onInit, []);

Я бы предпочел, чтобы проблема была решена на стороне линтинга, но эй ...

@ ra30r - хороший обходной путь, но вам интересно, может ли он вызвать побочные эффекты? : мышление:

Еще ничего? 😔

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

Это вызвало "отправку" отсутствующей зависимости, но все равно работало:

  useEffect(() => {
    if (state.business_name.value) {
      const delay = setTimeout(() => dispatch({ type: "businessNameAfterDelay" }), 1000)
      return () => clearTimeout(delay)
    }
  }, [state.business_name.value])

Используя пример @ra30r , я изменил его на это, чтобы сбросить ошибку:

  const businessNameAfterDelay = function () {
    if (state.business_name.value) {
      const delay = setTimeout(() => dispatch({ type: "businessNameAfterDelay" }), 1000)
      return () => clearTimeout(delay)
    }
  }

  useEffect(businessNameAfterDelay, [state.business_name.value])

Почему это закрыто?

Я считаю, что где-то был дан ответ ... лол ... в любом случае ... решение состоит в следующем:
useEffect(() => { dispatch(); }, [dispatch]);

надеюсь это поможет!!

Почему это закрыто?

Я считаю, что где-то был дан ответ ... лол ... в любом случае ... решение состоит в следующем:
useEffect(() => { dispatch(); }, [dispatch]);

надеюсь это поможет!!

Да, это обходное решение работает, - сказал здесь
Почему вопрос закрыт? Здесь тоже есть мемы по этому поводу ... xd

Моя проблема вроде этого (пример кода):

  const [userStatus, setUserStatus]: any = React.useState([]);
  const [userData, setUserData]: any = React.useState([]);

  useEffect(() => {
    setUserStatus(!userStatus);
    return () => {};
  }, [userData]);

Итак, как и в коде, вы хотите изменить значение userStatus когда есть изменение в userData и в этом случае, если вы хотите проверить значение userStatus вы должны добавить его в deps:

  const [userStatus, setUserStatus]: any = React.useState([]);
  const [userData, setUserData]: any = React.useState([]);

  useEffect(() => {
    setUserStatus(!userStatus);
    return () => {};
  }, [userData, userStatus]);

в этом сценарии это будет бесконечный цикл

@spmsupun
Вы можете использовать стиль обратного вызова useState, чтобы не вводить переменную userStatus в массив зависимостей useEffect.

 useEffect(() => {
    setUserStatus(prevState => !prevState);
    return () => {};
  }, [userData]);

А это так называемые функциональные обновления .

Решение → просто добавьте отправку в последнюю очередь для зависимости
У React Hook useEffect отсутствует зависимость: 'dispatch'.

  useEffect(() => {
    axios.get('http://localhost:8000/api/future-registrations')
      .then((result) => {
        dispatch(initRegistrationsAction(result.data));
      });
**  }, [dispatch]);**

@kennylbj Это хорошо, когда вы имеете дело с одним состоянием, мой реальный сценарий - с реквизитом. Я отправляю реквизит от родителя, и он меняется дважды, поэтому usereffect вызывает дважды, но я запускаю в нем слушателя, и он будет слушать дважды.

@spmsupun Но я думаю, что вполне нормально

Если вы все еще не хотите, чтобы прослушиватель вызывался дважды, я думаю, вам следует больше позаботиться о передаваемых ему реквизитах и ​​убедиться, что он не будет изменен во время рендеринга.

@kennylbj ну, я
image
Думаю, мне нужно справиться с этим из класса слушателя,

Похоже, ваш слушатель вызывается дважды, даже если идентификатор сокета одинаковый.

Я не думаю, что это произойдет, если встретится следующая ситуация:

ts // call useEffect if and only if sockeId changed. useEffect(() => { const unregister = register(socketId); return () => unregister(socketId); }, [socketId])

Есть ли какие-либо другие переменные в массиве зависимостей, измененные во время разных рендеров и вызывающие такое поведение?

Да 3 зависимости, но я понимаю это иначе

Пьен

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

const initFetch = useCallback(() => {
    dispatch(fetchPosts());
  }, [dispatch]);

  useEffect(() => {
    initFetch();
  }, [initFetch]);

вау , 非常 感谢 你 🙏

🚀 Приведенный ниже фрагмент кода мне очень подходит

На Компонент действительно монтировался

const onInit = () => getUsers()
useEffect(onInit, [])

При изменении параметра

const onInit = () => getUser(id)
useEffect(onInit, [id])

Лучшее решение: react-hooks / excustive-deps: "off"
Я никогда не считал эту функцию eslint полезной. Всегда.

🚀 Приведенный ниже фрагмент кода мне очень подходит

На Компонент действительно монтировался

const onInit = () => getUsers()
useEffect(onInit, [])

При изменении параметра

const onInit = () => getUser(id)
useEffect(onInit, [id])

хорошая работа.

Я не думаю, что документы по реакции полностью охватывают вариант использования

У нас есть несколько способов вызвать данную функцию, например: setCenterPosition() . Его можно вызвать, наблюдая за изменением состояния (подключено через useEffect ), обработчиком кликов (вызывается напрямую) и т. Д.

В ответных документах предлагается

Вот почему обычно вы хотите объявлять функции, необходимые для эффекта внутри него.

Но обычно в реальных примерах нам нужно повторно использовать функции, как обычно с методами экземпляра в компоненте класса ( this.setCenterPosition(...) ), и я начинаю задаваться вопросом, действительно ли хуки хороши для полнофункциональной, сложные компоненты.

Я не совсем уверен, но, возможно, решение - useCallback

const setCenterPosition = useCallback(() => {
  ...
}, [Stage, elePositionArr, setElePositionArr]);

useEffect() => {
  ...
}, [stageRef, Stage, currentIndex, setCenterPosition]);

... но для меня это довольно мерзко, и я надеюсь, что есть способ чище. Может, @gaearon подтвердит?

столкнувшись с той же проблемой, я могу отключить предупреждение bu, используя эту строку в конце useEffect // eslint-disable-next-line react-hooks/exhaustive-deps но я не хочу ее использовать

Вот мой код

`const [items, setItems] = useState ([
{
название: "тест 1",
id: 1
},
{
название: "тест 2",
id: 2
},
{
название: "тест 3",
id: 3
},
{
название: "тест 4",
id: 4
},
{
название: "тест 5",
id: 5
}
]);

useEffect (() => {
const intervalId = setInterval (() => {
setItems (shuffleArray (items));
}, 1000);
return () => {
clearInterval (intervalId);
};
// eslint-disable-next-line перехватчики реакции / исчерпывающие-deps
}, []);

Мое решение этой проблемы состояло в том, чтобы просто прекратить использовать React Hooks для этих случаев. Если компоненту так сильно нужна логика состояния и события жизненного цикла, такие как componentDidMount , просто используйте компонент класса и избавьтесь от головной боли. Компоненты класса в полном порядке, и если этот поток что-то доказывает, так это то, что React Hooks не готовы полностью заменить их, когда требуется сложная логика состояния или события жизненного цикла (и они не дают никаких преимуществ в большинстве этих случаев - действительно ли ваш код _ что намного лучше, если вы использовали React Hooks?).

Я ограничу свое собственное использование React Hooks простыми, такими как useState для установки логических флагов и тому подобного. Если компонент когда-либо становится достаточно сложным, чтобы потребовать useEffect я рассматриваю это как знак того, что, возможно, компонент класса просто лучше подходит.

(Отредактировано для наглядности).

На данный момент это мое решение:

const mounted = () => {
  dispatch(something());
}

useEffect(mounted, []);

Спасибо @ ra30r response / issues / 15865 # issuecomment-651254164

Была ли эта страница полезной?
0 / 5 - 0 рейтинги