仅设置一次状态

时间:2020-03-10 15:38:35

标签: reactjs state jsx use-effect

我正在使用一个函数(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中(在App.js:60)

我的问题是如何让此功能仅运行一次?

3 个答案:

答案 0 :(得分:5)

功能组件主体中的任何内容都会运行每个渲染。更改为useEffect是解决此问题的正确方法。

它对您不起作用,因为useEffect array 作为其第二个参数,而不是 object 。将其更改为[],它将仅运行一次。

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 hook here的更多信息。

答案 1 :(得分:1)

您需要清理useEffect之类的

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

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

看看这个article。它说明了为什么要清理useEffect。

答案 2 :(得分:0)

在设置状态之前,您仍然没有检查是否已安装组件。您可以为此使用自定义钩子:

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]);