React useState hook 返回旧的状态值,尽管它被更新了



我想:

  1. 将图像上传到浏览器中(我使用 React Dropzone 执行此操作。我下面的uploadImage函数在将文件拖放到拖放区时运行。
  2. 使用文件读取器 API 将图像作为实际图像读取。
  3. 使用 React Hooks 将图像文件和图像元数据保存到 state 中。
  4. 进行 API 调用,将此映像推送到服务器。

我正在尝试确认我在步骤 4 中拥有图像,但我无法通过控制台消息确认。尽管日志消息显示状态已更新,但我还是以某种方式坚持使用原始状态值。

我尝试为所有内容添加额外的异步,并且我已经将内容包装在承诺中。我可以确认readImage功能正常。我可以确认运行序列是readImagesaveImagesetGraphic在 saveImage 中,然后是控制台.log在uploadImage中应该具有更新的值但没有。

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 钩子正在做一些时髦的事情。 进程在启动时复制值,而不是在读取控制台.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 中批处理),然后它会调用传入新计数的整个组件函数。

因此,尝试awaitsetState 调用是没有意义的,在它之前和之后记录状态也是没有意义的(因为它不会在两者之间更改)。在组件中记录一次,如果设置状态,则整个组件将再次执行,并且日志记录将记录新状态。

相关内容

  • 没有找到相关文章

最新更新