在useState钩子中设置状态后,React状态变量不准确



我有一个React函数组件与遗留的JQuery应用程序一起运行。在JQuery元素上调用事件处理程序时,传入的当前React状态默认为初始状态值,而不是更新后的状态值。

已验证的x状态通过useEffect挂钩进行更改,但在调用事件侦听器时,x被设置为初始状态值,而不是更新后的状态值。

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.
};
}

不会显示任何错误消息。在上面的代码中,我希望onXSave方法调用中的x状态为true,但它一直显示为false。

要添加到eventListeneronXSave版本已过期-您在第一次渲染时只添加一次,因此当x更新并导致重新渲染时,useEffect不会再次运行,jQueryButton仍将保留原始函数,该函数已因x的过期版本而关闭。

你需要做两件事:

  1. onXSavejQueryButton添加为useEffect依赖数组中的依赖项(因此,当它重新渲染时,函数的当前版本将连接到eventListener(
  2. 通过从useEffect返回一个清理函数,在重新渲染时删除旧的事件侦听器

所以类似于:

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.
};

}

onXSave被添加为初始渲染的处理程序,因此x具有当时的值。在每次渲染中重新创建onXSave并不重要,因为它从未在初始渲染后使用过。

要解决此问题,您可以将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
};
}

最新更新