只设置状态一次
Set State only once
我正在使用一个函数 (getActorInfo()) 来响应从 api 中获取信息并将其设置为状态。它有效,但功能不会停止 运行ning。
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));
}, {});
但是我得到一个我不明白的错误
Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
in ActorProfile (at App.js:60)
我的问题是这个功能如何只运行一次?
功能组件主体中的任何内容都会 运行 每次渲染。改成useEffect
才是解决这个问题的正确方法。
它不适合你,因为 useEffect
将 array 作为第二个参数,而不是 object。改成[]
,只会运行一次。
useEffect(() => {
getActorInfo(id).then(val => setActorInfo(val));
}, []);
这将等同于基于 class 的 componentDidMount
。
如果你的钩子有一个依赖项,你将它添加到数组中。然后 effect 将检查依赖项数组中的任何内容是否发生了变化,只有 运行 钩子是否发生了变化。
useEffect(() => {
// You may want to check that id is truthy first
if (id) {
getActorInfo(id).then(val => setActorInfo(val));
}
}, [id]);
任何时候 id
变化的结果都是 运行,只有当 id
为真时才会调用 getActorInfo
。这相当于基于 class 的 componentDidMount
和 componentDidUpdate
.
您可以阅读有关 useEffect
hook here 的更多信息。
你需要像
一样清理 useEffect
useEffect(() => {
getActorInfo(id).then(val => setActorInfo(val));
return () => {
setActorInfo({});
}
},[]);
看看这个 article。它解释了为什么要清理 useEffect。
您仍然没有在设置状态之前检查组件是否已安装。您可以为此使用自定义挂钩:
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]);
我正在使用一个函数 (getActorInfo()) 来响应从 api 中获取信息并将其设置为状态。它有效,但功能不会停止 运行ning。
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));
}, {});
但是我得到一个我不明白的错误
Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function. in ActorProfile (at App.js:60)
我的问题是这个功能如何只运行一次?
功能组件主体中的任何内容都会 运行 每次渲染。改成useEffect
才是解决这个问题的正确方法。
它不适合你,因为 useEffect
将 array 作为第二个参数,而不是 object。改成[]
,只会运行一次。
useEffect(() => {
getActorInfo(id).then(val => setActorInfo(val));
}, []);
这将等同于基于 class 的 componentDidMount
。
如果你的钩子有一个依赖项,你将它添加到数组中。然后 effect 将检查依赖项数组中的任何内容是否发生了变化,只有 运行 钩子是否发生了变化。
useEffect(() => {
// You may want to check that id is truthy first
if (id) {
getActorInfo(id).then(val => setActorInfo(val));
}
}, [id]);
任何时候 id
变化的结果都是 运行,只有当 id
为真时才会调用 getActorInfo
。这相当于基于 class 的 componentDidMount
和 componentDidUpdate
.
您可以阅读有关 useEffect
hook here 的更多信息。
你需要像
一样清理 useEffectuseEffect(() => {
getActorInfo(id).then(val => setActorInfo(val));
return () => {
setActorInfo({});
}
},[]);
看看这个 article。它解释了为什么要清理 useEffect。
您仍然没有在设置状态之前检查组件是否已安装。您可以为此使用自定义挂钩:
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]);