[英]React state variable not accurate after set state in useState hook
I have a React function component running along side a legacy JQuery application.我有一个 React function 组件与旧版 JQuery 应用程序一起运行。 When calling an event handler on a JQuery element, passing in the current React state defaults to the initial state value and not the updated state value.
When calling an event handler on a JQuery element, passing in the current React state defaults to the initial state value and not the updated state value.
Verified x state is changing through a useEffect hook, but when calling the event listener, x is set to the initial state value and not the state value after the update.已验证 x state 正在通过 useEffect 挂钩进行更改,但在调用事件侦听器时,x 设置为初始 state 值,而不是更新后的 state 值。
function MyComponent(props) {
const [x, setX] = useState(false);
// On initial render
useEffect(() => {
props.jQueryButton.addEventListener('click', onXSave)
}, [])
useEffect(() => {
console.log("x changed " + x); // everytime onXChange is called, x
state is updated with the checked value, and this console.log shows
the correct state value
}, [x]);
onXChange = event => {
setX(event.target.checked); // checked is true in this context
};
onXSave = event => {
const obj = { x: x}; // x is false here, even though the state in this context shows it to be true.
};
}
No error messages are displayed.不显示错误消息。 In the above code in this context I expect the x state to be true in the onXSave method call, but it keeps displaying as false.
在上面的代码中,我希望 x state 在 onXSave 方法调用中为真,但它一直显示为假。
onXSave
is added as a handler on initial render so x
has the value from that time. onXSave
在初始渲染时添加为处理程序,因此x
具有当时的值。 It doesn't matter that onXSave
is recreated on each render since it's never used past initial render.在每次渲染时重新创建
onXSave
并不重要,因为它从未使用过初始渲染。
To fix this you might put x
into a ref
要解决此问题,您可以将
x
放入ref
unction MyComponent(props) { const [x, setX] = useState(false); const ref = useRef(); ref.current = x; // On initial render useEffect(() => { props.jQueryButton.addEventListener('click', onXSave) }, []) useEffect(() => { console.log("x changed " + x); // everytime onXChange is called, x state is updated with the checked value, and this console.log shows the correct state value }, [x]); onXChange = event => { setX(event.target.checked); // checked is true in this context }; onXSave = event => { const obj = { x: ref.current}; // by using ref, the value is always current }; }
The version of onXSave
that you're adding to your eventListener
is out of date - you only add it once on the first render, so when x
updates and causes a re-render, your useEffect doesn't run again and your jQueryButton
will still holding on to the original function, which has closed over an out of date version of x
.您添加到
eventListener
的onXSave
版本已过期 - 您仅在第一次渲染时添加一次,因此当x
更新并导致重新渲染时,您的 useEffect 不会再次运行,您的jQueryButton
仍将保留原来的 function,它已经关闭了一个过时的x
版本。
You need to do two things:你需要做两件事:
onXSave
and your jQueryButton
as dependencies in your useEffect
dependency array (so when it re-renders, the current version of your function is hooked up to your eventListener)useEffect
依赖数组中添加onXSave
和你的jQueryButton
作为依赖(所以当它重新渲染时,你的 function 的当前版本连接到你的 eventListener)useEffect
.useEffect
返回清理 function 来删除重新渲染时的旧事件侦听器。 So something like:所以像:
function MyComponent(props) {
const [x, setX] = useState(false);
// On initial render
useEffect(() => {
props.jQueryButton.addEventListener('click', onXSave)
return ()=> props.jQueryButton.removeEventListener('click', onXSave)
}, [onXSave, props.jQueryButton])
useEffect(() => {
console.log("x changed " + x); // everytime onXChange is called, x
state is updated with the checked value, and this console.log shows
the correct state value
}, [x]);
onXChange = event => {
setX(event.target.checked); // checked is true in this context
};
onXSave = event => {
const obj = { x: x}; // x is false here, even though the state in this context shows it to be true.
};
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.