如何在组件卸载中使用useEffect挂钩有条件地运行代码

时间:2020-09-30 14:38:05

标签: reactjs react-hooks

出于某种奇怪的原因,我的“ unmount” useEffect挂钩中的prop值始终处于原始状态(true),我可以进行控制台操作,并在devtools中看到它已更改为false,但是当对unmount调用useEffect时永远是真的。
我尝试过将道具添加到依赖项中,但是它不再仅在卸载时调用,也无法满足其目的。
编辑:我知道依赖数组为空,我无法在每次更改时都触发它,只有在用props的更新值卸载后才需要触发它。这可能吗?

React.useEffect(() => {
    return () => {
      if (report.data.draft) { // this is ALWAYS true
        report.snapshot.ref.delete();
      }
    };
  }, []);

如何在条件依赖于更新的道具状态的情况下有条件地在卸载时运行代码?

3 个答案:

答案 0 :(得分:2)

效果的依赖项列表为空,这意味着react只会在装入后在外部变量上创建闭包,并且函数将仅在装入时看到它们的值。要在React.useEffect(() => { return () => { if (report.data.draft) { // this is ALWAYS true report.snapshot.ref.delete(); } }; }, [report.data.draft]); 更改时重新创建闭包,必须将其添加到依赖项列表中:

{{1}}

还有一个eslint插件,警告您缺少依赖项:https://www.npmjs.com/package/eslint-plugin-react-hooks

答案 1 :(得分:1)

如果要使代码仅在卸载时运行,则需要使用空的依赖项数组。如果您还需要封闭中的数据,这些数据可能在第一次渲染组件和最后一次渲染组件之间发生变化,那么您需要使用ref使数据在卸载时可用。例如:

const onUnmount = React.useRef();
onUnmount.current = () => {
  if (report.data.draft) {
    report.snapshot.ref.delete();
  }
}
React.useEffect(() => {
  return () => onUnmount.current();
}, []);

如果您经常这样做,则可能要将其提取到自定义钩子中:

export const useUnmount = (fn): => {
  const fnRef = useRef(fn);
  fnRef.current = fn;

  useEffect(() => () => fnRef.current(), []);
};


// used like:
useUnmount(() => {
  if (report.data.draft) {
    report.snapshot.ref.delete();
  }
});

答案 2 :(得分:0)

使用自定义 js 事件,您可以模拟卸载 componentWillUnmount,即使存在依赖关系。我是这样做的。

问题:

    useEffect(() => {
    //Dependent Code
    return () => {
        // Desired to perform action on unmount only 'componentWillUnmount' 
        // But it does not
        if(somethingChanged){
            // Perform an Action only if something changed
        }
    }
},[somethingChanged]);

解决方案:

// Rewrite this code  to arrange emulate this behaviour

// Decoupling using events
useEffect( () => {
    return () => {
        // Executed only when component unmounts,
        let e = new Event("componentUnmount");
        document.dispatchEvent(e);
    }
}, []);

useEffect( () => {
    function doOnUnmount(){
        if(somethingChanged){
            // Perform an Action only if something changed
        }
    }

    document.addEventListener("componentUnmount",doOnUnmount);
    return () => {
        // This is done whenever value of somethingChanged changes
        document.removeEventListener("componentUnmount",doOnUnmount);
    }

}, [somethingChanged])

注意事项: useEffects 必须是有序的,没有依赖的 useEffect 之前必须写,这是为了避免事件被删除后调用。