这似乎是一个无法解决的独特问题,因为我无法使用纯JavaScript复制它。问题是我在函数中使用状态变量,但是函数将使用定义函数时变量具有的值,而不是变量的当前值:
import React, { useEffect, useState } from 'react';
export default function Home() {
const [val, setVal] = useState(0);
const [f, setF] = useState(null);
useEffect(function(){
setF(()=>function(){console.log(val)})
setVal(2)
},[])
console.log("Value is", val)
return (
<div
onClick={f}
style={{
backgroundColor: 'red',
height: 100,
width: 100,
}}
>
</div>
)
}
单击div后,输出为:
Value is 0
Value is 2
0
很明显,变量val被更新为2,但是当运行函数f时,它会打印出函数定义时val的值,而不是新的更新值。
我已经通过在函数依赖于状态值的任何时间重新定义函数来解决此问题,但这并不理想,因为我希望函数始终使用新值。在普通的javascript中似乎不会发生这种情况,或者至少我无法弄清楚如何实现。
为什么会这样?是否可以进行不需要我重新定义功能的修复程序?这是独一无二的反应吗?
答案 0 :(得分:1)
正如@Tuhin指出的那样,简短的答案是闭包。当您定义setF(()=>function(){console.log(val)})
时,val = 0,此后函数定义都没有改变,因此f
在创建val时便关闭了val的值。您可以在代码中添加console.dir(f)
进行检出:
答案 1 :(得分:0)
在您的代码中,f
更新时val
没有更新。
如果您将useEffect
作为val
的依赖项,则将解决该问题。
您可以看到it。
答案 2 :(得分:0)
据我了解,您想通过val
函数打印最近的f
。
但是问题是,
setF(()=>function(){console.log(val)})
<-此行。
val将始终为0,因为它被分配了一次,并且将通过值而不是引用来调用。就像setTimeout的工作原理一样。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop