首页 > 解决方案 > 反应清理功能不清理状态

问题描述

请各位高手解释一下,为什么在下面的代码中,属性的状态不会在useEffect清理函数中被清理?

我的组件:

export default function TestComp() {

  let { id } = useParams();
  const [value, setValue] = useState(null);
  console.log('[TestComp] called...');

  const cleanup = () => {
    console.log('[TestComp] old value', value);
    setValue(null);
  };

  useEffect(() => {
    console.log('[TestComp] id changed: ', id);
    console.log('[TestComp] value in useEffect', value);
    setValue(id);
    return () => {
      cleanup();
    }
  }, [id]);

  return (<React.Fragment>Test id: {id}</React.Fragment>)
}

控制台输出:

[TestComp] called... TestComp.js:8
[TestComp] old value satellites:MTP TestComp.js:11
[TestComp] id changed:  satellites:MTP TestComp.js:16
[TestComp] value in useEffect satellites:FPGA TestComp.js:17
[TestComp] called... 2 TestComp.js:8
[TestComp] old value satellites:FPGA TestComp.js:11
[TestComp] id changed:  satellites:FNE TestComp.js:16
[TestComp] value in useEffect satellites:MTP TestComp.js:17
[TestComp] called... TestComp.js:8

我希望,当 useEffect 将被调用 2. 时间时,该将被清理并为null,但它仍保留旧值:

value in useEffect satellites:MTP TestComp.js:17

先感谢您。

标签: reactjsstateuse-effect

解决方案


useEffect 的返回函数只是在应用下一个效果之前清理以前的效果。但是您的代码中的主要问题是

    const cleanup = () => {
    console.log('[TestComp] old value', value);
    setValue(null); // This is not prefer way to use setValue here.
}

通常,在清理期间,我们取消订阅外部服务/订阅,但在这里您正在更改此处没有意义的状态,并立即通过运行的 useEffect setValue获取更新,并且在调用清理内部的setValue之后,这也是再次调用效果的原因,

在你的 useEffect 中添加 setTimeout 后检查你的代码。

`useEffect(() => {
    console.log('[TestComp] id changed: ', id);
    console.log('[TestComp]:Effect value in useEffect', value);
    setValue(id);
    return () => {
      setTimeout(()=> cleanup(), 5000)
    }
  }, [id]);`

可能的解决方案 -

  • 在上述情况下,您使用id,将此属性提升到父组件并将其作为属性传递给 TestComp 组件。

  • 当效果运行时,整个组件会重新渲染,作用域会被破坏,但所有状态都保持在useState钩子的闭包内。

上述情况的工作示例


推荐阅读