我正在使用React上下文传递状态。当我的状态更改时,子组件中的状态也会更改(控制台日志显示新值),但是在函数中使用此状态时,它不会在那里更新(console.log显示旧值)。
我需要重新渲染功能吗?怎么样?
const {user, userInfo, ref} = useSession(); <-- wrapper for useContext
console.log(userInfo); <--- correct, updated value
const haalDataOp = async () => {
console.log(userInfo.enelogic); <--- old value displaying
...
}
我正在通过按钮(onClick)使用功能haalDataOp
正如已经提到的那样,我可以使用useRef,但是我不明白为什么。为什么这个简单的示例起作用(从https://dev.to/anpos231/react-hooks-the-closure-hell-71m中提取),而我的代码却没有:
const [value, setValue] = useState(1);
const handleClick = useCallback(
() => {
setValue(value + 1)
},
[value],
);
在示例中,我还尝试使用useCallback(在dep数组中带有userInfo),但这不能解决问题。
答案 0 :(得分:1)
const ... userInfo ...
是一个常量,因此在如下组件中:
console.log('render', userInfo.enelogic) // different value in each render
const haalDataOp = async () => {
console.log('before', userInfo.enelogic) // correct old value
await update()
console.log('after', userInfo.enelogic) // still the same old value
}
return <button onClick={haalDataOp} />
...它将记录:
render old
before old
after old
render new
...因为userInfo
中的haalDataOp
是一个闭包,引用了原始渲染器中的值。如果您需要访问一个可变的引用,该引用将指向将来渲染中的最新值,则可以useRef:
const userInfoRef = useRef()
userInfoRef.current = userInfo
console.log('render', userInfo.enelogic) // different value in each render
const haalDataOp = async () => {
console.log('before', userInfoRef.current.enelogic) // old value
await update()
console.log('after', userInfoRef.current.enelogic) // should be new value
}
return <button onClick={haalDataOp} />
但是,可能存在竞争条件和/或'after'
代码的执行确定性地发生在下一次渲染之前,在这种情况下,您将需要使用其他技巧...
我怀疑正是这种情况需要const {ref} = useSession()
,所以请阅读文档。