我正在使用一个函数(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)
我的问题是如何让此功能仅运行一次?
答案 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]);