Установить состояние только один раз - PullRequest
2 голосов
/ 10 марта 2020

Я использую функцию (getActorInfo ()) для реакции на получение информации из API и установки ее в State. Это работает, но функция не остановится.

export default function ActorProfile({ name, img, list, id, getActorInfo }) {
  const [showList, setShowList] = useState(false);
  const [actorInfo, setActorInfo] = useState({});

  getActorInfo(id).then(val => setActorInfo(val));

  console.log(actorInfo)

  return (
    <Wrapper>
      <Actor
        id={id}
        name={name}
        img={img}
        onClick={() => {
          setShowList(!showList);
        }}
        actorBirthday={actorInfo.actorBirthday}
      />
      {showList && <MovieList list={list} actorInfo={actorInfo} />}
    </Wrapper>
  );
}

Я пытался использовать useEffect следующим образом

  useEffect(() => {
    getActorInfo(id).then(val => setActorInfo(val));
  }, {});

Но я получаю ошибку, которую не понимаю

Невозможно выполнить состояние React обновление неустановленного компонента. Это неоперация, но она указывает на утечку памяти в вашем приложении. Чтобы исправить, отмените все подписки и асинхронные задачи в функции очистки useEffect. в ActorProfile (в приложении js: 60)

Мой вопрос: как запустить эту функцию только один раз?

Ответы [ 3 ]

5 голосов
/ 10 марта 2020

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

Это не работает для вас, потому что useEffect принимает массив в качестве второго параметра, а не объект . Измените его на [], и он будет работать только один раз.

useEffect(() => {
  getActorInfo(id).then(val => setActorInfo(val));
}, []);

Это будет эквивалентно основанному на классе componentDidMount.

Если ваш хук имеет зависимость, вы добавить его в массив. Затем эффект проверит, изменилось ли что-нибудь в вашем массиве зависимостей, и запустит ловушку, только если он имеет.

useEffect(() => {
  // You may want to check that id is truthy first
  if (id) {
    getActorInfo(id).then(val => setActorInfo(val));
  }
}, [id]);

Полученный эффект будет запущен при любых изменениях id и вызовет только getActorInfo, если id является правдой. Это эквивалентно классам componentDidMount и componentDidUpdate.

Подробнее о хуке useEffect можно прочитать здесь .

1 голос
/ 10 марта 2020

вам нужно очистить useEffect, как

useEffect(() => {
getActorInfo(id).then(val => setActorInfo(val));

return () => {
  setActorInfo({});
}
},[]);

, посмотрите на эту статью . Это объясняет вам, почему для очистки используйте Effect.

0 голосов
/ 10 марта 2020

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

const useIsMounted = () => {
  const isMounted = useRef(false);
  useEffect(() => {
    isMounted.current = true;
    return () => (isMounted.current = false);
  }, []);
  return isMounted;
};

Тогда в вашем компоненте вы можете сделать:

const isMounted = useIsMounted();

useEffect(() => {
  getActorInfo(id).then(
    val => isMounted && setActorInfo(val)
  );
}, [getActorInfo, id, isMounted]);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...