如何等待反应异步 setStates

时间:2021-07-26 07:11:43

标签: reactjs asynchronous promise

我正在尝试将文件上传到状态变量中。

function CreateCarouselPost() {
  const [file, setFile] = useState(null);
  
  const handleFileUpload = (e) => {
    setFile(e.target.files[0]); 
    console.log(file); // file is still null 
  }

  return (
    <div className='create-carousel-container'>
      <h2 className='create-carousel-header'>Add Images and Videos</h2>
      <div className='create-carousel-grid'>
        <div className='add-image-video-card grid-item'>
          <input
            className='carousel-file-upload'
            type='file'
            name='content'
            accept='image/*,video/*'
            onChange={handleFileUpload}
          />
        </div>
      </div>
    </div>
  );
}

但是我知道 setState 是异步的并且需要时间。所以当我在 setFile 之后立即使用 console.log 文件时,文件仍然为空。当我上传另一个文件时,它包含前一个文件的内容。所以,我试图通过使用 Promises 来等待它,但我无法让它工作。

import React, { useState, useEffect } from 'react';
import AddIcon from '@material-ui/icons/Add';
import './styles/Carousel.css';

function CreateCarouselPost() {
  const [file, setFile] = useState(null);

  const uploadFile = (file) => {
    return new Promise((resolve) => {
      setFile(file);
      resolve();
    });
  };

  const handleFileUpload = (e) => {
    uploadFile(e.target.files[0]).then(() => {
      console.log('file = ', file);
    });
  };

  return (
    <div className='create-carousel-container'>
      <h2 className='create-carousel-header'>Add Images and Videos</h2>
      <div className='create-carousel-grid'>
        <div className='add-image-video-card grid-item'>
          <input
            className='carousel-file-upload'
            type='file'
            name='content'
            accept='image/*,video/*'
            onChange={handleFileUpload}
          />
        </div>
      </div>
    </div>
  );
}

export default CreateCarouselPost;

据我的理解,Promise 会在里面的所有代码都执行完然后调用 resolve 函数后被解析。所以我尝试将它放在 Promise 中并尝试访问 resolve() 中的文件状态。但事实证明问题仍然相同(未获得最新值)。请帮助以正确的方式做到这一点。

1 个答案:

答案 0 :(得分:1)

你应该使用 useEffect 钩子。这将作为状态设置后的回调。

例如:

function CreateCarouselPost() {
  const [file, setFile] = useState(null);
  
  const handleFileUpload = (e) => {
    setFile(e.target.files[0]); 
  }

  useEffect(() => {
    console.log(file); // after file has been added to state
  }, [file]);

  return (
    <div className='create-carousel-container'>
      <h2 className='create-carousel-header'>Add Images and Videos</h2>
      <div className='create-carousel-grid'>
        <div className='add-image-video-card grid-item'>
          <input
            className='carousel-file-upload'
            type='file'
            name='content'
            accept='image/*,video/*'
            onChange={handleFileUpload}
          />
        </div>
      </div>
    </div>
  );
}

这是 useEffect 的文档: https://reactjs.org/docs/hooks-effect.html