首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >React清理功能不清理状态

React清理功能不清理状态
EN

Stack Overflow用户
提问于 2019-12-10 08:16:50
回答 3查看 2.5K关注 0票数 2

专家们,请解释一下,为什么在下面的代码中,属性的状态不会在useEffect清理函数中被清除?

我的组成部分:

代码语言:javascript
复制
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>)
}

控制台输出:

代码语言:javascript
复制
[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

我希望,当第2次调用useEffect时,将被清除并为空,但它仍然保留旧值:

代码语言:javascript
复制
value in useEffect satellites:MTP TestComp.js:17

提前谢谢你。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-12-10 11:25:21

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

代码语言:javascript
复制
    const cleanup = () => {
    console.log('[TestComp] old value', value);
    setValue(null); // This is not prefer way to use setValue here.
}

通常情况下,在清理过程中,我们取消了外部服务/订阅,但这里您更改的状态在这里没有意义,并立即得到运行的useEffect setValue的更新,以及在调用setValue之后立即更新,这也是再次调用效果的原因。

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

代码语言:javascript
复制
`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钩子的闭包中维护。

上述情况下的工作实例

票数 1
EN

Stack Overflow用户

发布于 2019-12-10 09:44:39

您可能需要添加另一个useEffect,因为在当前情况下,cleanup函数将只在卸载上运行,这对当前逻辑非常无用。

代码语言:javascript
复制
export default function TestComp() {
  let { id } = useParams();
  const [value, setValue] = useState(null);
  console.log('[TestComp] called...');

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

    /* v Useless cleanup because the component unmounts anyway,
         the `value` state will be cleaned automatically.
    return () => {
      cleanup();
    }
    */
  }, [id]);

  // ^ Firstly, the `value` changed on id change
  // v Secondly, the `value` will be reset on `value` change
  useEffect(() => {
    console.log('[TestComp] old value', value);
    setValue(null);
  }, [value]);

  return <>Test id: {id}</>;
}
票数 1
EN

Stack Overflow用户

发布于 2019-12-10 08:59:14

我认为这是事情发生的顺序的问题。

useEffect将在调用闭包时,即当调用TestComp函数时,作为闭包的一部分来“捕获”值。当id更改响应时,将调度对清除函数的调用,然后对效果进行调用。但是,直到调用了新的效果函数之后,才会再次调用TestComp

您可以在日志中看到这一点,因为清除函数中的每个old value都紧跟在id changed之后。

而且,由于新的效果函数从调用TestComp时‘捕获’值,它将不会看到由清理函数设置的值。

另外,请注意,至少从测试中我看到了React抱怨valuecleanup不存在于useEffect的依赖项中。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59262857

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档