简体   繁体   English

在 useState 挂钩中设置 state 后反应 state 变量不准确

[英]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 .您添加到eventListeneronXSave版本已过期 - 您仅在第一次渲染时添加一次,因此当x更新并导致重新渲染时,您的 useEffect 不会再次运行,您的jQueryButton仍将保留原来的 function,它已经关闭了一个过时的x版本。

You need to do two things:你需要做两件事:

  1. Add 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)
  2. Remove the old event listener on re-renders by returning a clean-up function from your 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM