reactjs 等待React中的useState

jfgube3f  于 2022-11-22  发布在  React
关注(0)|答案(3)|浏览(171)

我已经和这个代码斗争了好几天了,但我还是没有把它弄对。
问题在于:我正在处理一个有放置区的表单。在提交处理程序中,我需要将图片的url保存在一个数组中,但是它总是作为一个空数组返回。
宣告影像数组:

const [images, setImages] = useState([]);

在这里,我获取图像的url并尝试将其保存在数组中:

const handleSubmit = () => {

      files.forEach(async(file)=> {
          const bodyFormData = new FormData();
          bodyFormData.append('image', file);
          setLoadingUpload(true);
          try {
            const { data } = await Axios.post('/api/uploads', bodyFormData, {
              headers: {
                'Content-Type': 'multipart/form-data',
                Authorization: `Bearer ${userInfo.token}`,
              },
            });
            setImages([...images,data])
            setLoadingUpload(false);
          } catch (error) {
            setErrorUpload(error.message);
            setLoadingUpload(false);
          }
      })
  }

下面我使用submitHandler函数调用handleSubmit():

const submitHandler = (e) => {

    e.preventDefault();
    handleSubmit();
   dispatch(
        createCard(
          name,
          images,
        )
      );
}

我知道这是因为它执行代码的顺序,但我找不到解决办法。非常感谢你提前!!!!

n53p2ov0

n53p2ov01#

问题

React状态更新是异步处理的,但是状态更新函数本身不是async,所以你不能等待更新发生。你只能从当前渲染周期访问状态值。这就是为什么images可能仍然是你的初始状态,一个空数组([])。

const submitHandler = (e) => {
  e.preventDefault();
  handleSubmit(); // <-- enqueues state update for next render
  dispatch(
    createCard(
      name,
      images, // <-- still state from current render cycle
    )
  );
}

溶液

我认为您应该重新考虑如何计算images的下一个状态,进行一次更新,然后使用useEffect钩子来调度具有更新后的状态值的操作。

const handleSubmit = async () => {
  setLoadingUpload(true);
  try {
    const imagesData = await Promise.all(files.map(file => {
      const bodyFormData = new FormData();
      bodyFormData.append('image', file);
      return Axios.post('/api/uploads', bodyFormData, {
        headers: {
          'Content-Type': 'multipart/form-data',
          Authorization: `Bearer ${userInfo.token}`,
        },
      });
    }));
    setImages(images => [...images, ...imagesData]);
  } catch(error) {
    setErrorUpload(error.message);
  } finally {
    setLoadingUpload(false);
  }
}

const submitHandler = (e) => {
  e.preventDefault();
  handleSubmit();
}

React.useEffect(() => {
  images.length && name && dispatch(createCard(name, images));
}, [images, name]);
ie3xauqp

ie3xauqp2#

为防止出现竞态条件,您可以尝试使用setImages和当前值,如下所示:

setImages(currentImages => [...currentImages, data])

这样,您将准确使用当前包含在您的状态中的内容,因为images在这种情况下可能不是正确的。
作为另一个提示,我建议你不要循环遍历你的文件,而是对文件进行map,就像files.map(...一样。这样,你就可以把所有的文件条目Map到一个promise,最后,把它们合并到一个包含所有请求的promise中。这样你就可以更好地观察它了。

jdg4fx2g

jdg4fx2g3#

只需要用一个await Promise.all()函数来调用你的map函数。

相关问题