反应挂钩无法在未安装的组件中执行setstate

时间:2019-09-28 19:30:26

标签: reactjs

const SideAd = () => {
    const [sideAd, setSideAd] = useState([])
    useEffect(() => {
            query()
    }, [])
    const query = async () => {
        const res = await getSideAd()
        Array.isArray(res) && setSideAd(res)
    }
    return (
        <div className="sideAdComponent">   
        </div>
    )
}

我只想在安装时发出请求,然后设置一个新状态。但是相反,我遇到了错误react hook cant perform setstate in an unmounted component

2 个答案:

答案 0 :(得分:3)

您可以在这里做两件事。

首先是使用清理功能(useEffect的回调中的返回值)来对抗useEffect中的比赛条件

const SideAd = () => {
    const [sideAd, setSideAd] = useState([])
    useEffect(() => {
      const isMounted = true;
      getSideAd().then(res => Array.isArray && isMounted && setSideAd(res))
      return () => {isMounted = false;}
    }, [])
    return (
        <div className="sideAdComponent">   
        </div>
    )
}

检查nice article at hackernoon以获得更详细的说明。在我看来,这种方法比取消请求更好(因为它不需要您修改请求者的代码)。

另一件事:也许最好在响应出现之前检查一下为什么卸载组件的原因。可能有正当的理由(例如,您已经离开,而尚未收到回应)。

但是也可能有一些HOC声明了内联组件构造函数,并导致重新创建所有子树而不是进行更新。因此值得花一些时间进行调查-因为可能存在尚未发现的隐藏错误(example)。

答案 1 :(得分:0)

您可以编写一个名为useIsMounted的自定义钩子:

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

const SideAd = () => {
  const [sideAd, setSideAd] = useState([]);
  useEffect(() => {
    query();
  }, []);
  const mounted = useIsMounted();
  const query = async () => {
    const res = await getSideAd();
    Array.isArray(res) && mounted.current && setSideAd(res);
  };
  return <div className="sideAdComponent"></div>;
};