[英]React useState hook returns old state value despite it being updated
我想要:
uploadImage
函数将onDrop of file运行到Dropzone。) 我试图确认我在步骤4中有图像,但我无法通过我的控制台消息确认。 尽管日志消息显示状态已经更新,但我仍然坚持原始状态值。
我已经尝试过为所有东西添加额外的asyncs,并且我已经在promises中包装了东西。 我可以确认readImage
函数没问题。 我可以确认运行顺序是readImage
, saveImage
, setGraphic
,然后是uploadImage
中的console.log,它应该具有更新的值但不具有更新的值。
const [graphic, setGraphic] = useState({ ...nullGraphic });
const readImage = async (img) => {
const reader = new FileReader();
return new Promise((resolve, reject) => {
reader.onerror = () => reader.abort();
reader.onabort = () => reject(new DOMException('Problem parsing input file.'));
reader.onload = () => resolve(reader.result);
reader.readAsDataURL(img);
});
};
const saveImage = async (img) => {
const imageRead = await readImage(img);
console.log(imageRead);
await setGraphic({
...graphic,
image: imageRead,
imageName: img.name,
imageType: img.type,
});
};
const uploadImage = async (img) => {
await saveImage(img);
console.log(graphic);
});
render() {
console.log(graphic);
return( <some dom> )
}
这是我奇怪的控制台序列:
Form.js:112 starting saveImage
Form.js:95 (snipped value of imageRead)
Form.js:237 {snipped updated values of graphic}
Form.js:114 done with saveImage
Form.js:116 {snipped original values of graphic}
我的理论
useState钩子正在做一些时髦的事情。 该进程在启动时复制值,而不是在读取console.log时读取它,因此uploadImage
函数在该进程的生命周期内获取useState挂钩的原始值。
如果我们将所有那些React魔法简化为以下内容,可能会清楚为什么这不起作用:
function withState(initial, fn) {
function setState(updated) {
setTimeout(() => fn(updated, setState), 0);
//...
}
setState(initial);
}
现在我们可以说明发生了什么:
withState(0, (counter, setCount) => {
console.log("before", counter);
if(counter < 10) setCount(counter + 1);
console.log("after", counter);
});
如您所见, setCount
不会直接更改状态( count
)。 实际上它根本不会改变本地count
变量。 因此“之前”和“之后”将始终记录相同(只要您不直接改变counter
)。
而是调用setCount
将被保护(并在React中进行批处理),然后它将调用传递新计数的整个组件函数。
因此,尝试await
setState调用没有任何意义,也没有必要记录它之前和之后的状态(因为它不会在中间变化)。 在组件中记录一次,如果设置状态,则整个组件再次执行,日志记录将记录新状态。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.