为什么我的 React 组件中的值没有更新?
Why isn't the value updating in my React component?
这似乎是一个独特的反应问题,因为我无法使用普通 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 中似乎不会发生这种情况,或者至少我无法弄清楚如何实现它。
为什么会这样?是否可以进行不需要我重新定义函数的修复?这是独一无二的反应吗?
在您的代码中,f
在 val
更新时没有更新。
如果您将 useEffect
作为依赖项提供给 val
,问题就会得到解决。
可以看到it.
据我了解,您想通过 f
函数打印最近的 val
。
但问题是,
setF(()=>function(){console.log(val)})
<-- 这一行。
val 将始终为 0,因为它被赋值一次,并且将按值调用,而不是按引用调用。就像 setTimeout 的工作原理一样。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop
正如@Tuhin 所指出的,简短的回答是闭包。当您定义 setF(()=>function(){console.log(val)})
时,val = 0 并且之后的任何时候都不会更改函数定义,因此 f
在其创建时关闭了 val 的值。您可以在代码中添加 console.dir(f)
来查看它:
这似乎是一个独特的反应问题,因为我无法使用普通 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 中似乎不会发生这种情况,或者至少我无法弄清楚如何实现它。
为什么会这样?是否可以进行不需要我重新定义函数的修复?这是独一无二的反应吗?
在您的代码中,f
在 val
更新时没有更新。
如果您将 useEffect
作为依赖项提供给 val
,问题就会得到解决。
可以看到it.
据我了解,您想通过 f
函数打印最近的 val
。
但问题是,
setF(()=>function(){console.log(val)})
<-- 这一行。
val 将始终为 0,因为它被赋值一次,并且将按值调用,而不是按引用调用。就像 setTimeout 的工作原理一样。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop
正如@Tuhin 所指出的,简短的回答是闭包。当您定义 setF(()=>function(){console.log(val)})
时,val = 0 并且之后的任何时候都不会更改函数定义,因此 f
在其创建时关闭了 val 的值。您可以在代码中添加 console.dir(f)
来查看它: