在 React 中等待 useState

pop*_*pop 10 reactjs react-hooks use-state

我已经与这段代码斗争了好几天了,但我仍然没有得到正确的结果。

问题:我正在使用具有拖放区的表单。在提交处理程序中,我需要将图像的 url 保存在数组中,但它总是作为空数组返回。

声明图像数组:

const [images, setImages] = useState([]);
Run Code Online (Sandbox Code Playgroud)

在这里,我获取图像的 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);
          }
      })
  }
Run Code Online (Sandbox Code Playgroud)

这里我有一个submitHandler函数,我在其中调用handleSubmit():

const submitHandler = (e) => {

    e.preventDefault();
    handleSubmit();
   dispatch(
        createCard(
          name,
          images,
        )
      );
}
Run Code Online (Sandbox Code Playgroud)

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

Dre*_*ese 12

问题

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
    )
  );
}
Run Code Online (Sandbox Code Playgroud)

解决方案

我认为您应该重新考虑如何计算 的下一个状态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]);
Run Code Online (Sandbox Code Playgroud)

  • 天哪,它成功了!!!!很好的解释,我现在明白了:)非常非常感谢!!!! (2认同)