繁体   English   中英

尽管它被更新,但React useState钩子返回旧的状态值

[英]React useState hook returns old state value despite it being updated

我想要:

  1. 将图像上传到浏览器中(我使用React Dropzone执行此操作。下面的uploadImage函数将onDrop of file运行到Dropzone。)
  2. 使用FileReader API将图像作为实际图像读取。
  3. 使用React Hooks将图像文件以及图像元数据保存到状态。
  4. 进行API调用,将此图像推送到服务器。

我试图确认我在步骤4中有图像,但我无法通过我的控制台消息确认。 尽管日志消息显示状态已经更新,但我仍然坚持原始状态值。

我已经尝试过为所有东西添加额外的asyncs,并且我已经在promises中包装了东西。 我可以确认readImage函数没问题。 我可以确认运行顺序是readImagesaveImagesetGraphic ,然后是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.

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