异步函数中的 setState

setState in async function

假设以下示例:

const example = () => {
    const [objects, setObjects] = useState([])

    const asyncFunction = async() => {

         // This will trigger the API and assume it takes around 10 seconds to run
         let result = api.fetchObjects().then((result) => {
             // Here, setObjects will be called with the value it had at the moment the function started executing, not the actual value
             setObjects(result)
         }
    }
}

我的问题是,执行 setObjects(result) 和使用更新状态的最佳方法是什么?假设用户可以在这 10 秒内通过应用程序中的不同方式将对象添加到该状态。

我找到了使用 useEffect 的解决方案,如下所示:

// Instead of setObjects(result)
const [updateObjects, setUpdateObjects] = useState(null)
setUpdateObjects(result)

useEffect(() => {
if (updateObjects !== null) {
setObjects(updateObjects)
setUpdateObjects(null)
}

您应该使用功能状态更新来访问和更新以前的状态。

functional updates

Note

Unlike the setState method found in class components, useState does not automatically merge update objects. You can replicate this behavior by combining the function updater form with object spread syntax:

const [state, setState] = useState({});
setState(prevState => {
  // Object.assign would also work
  return {...prevState, ...updatedValues};
});

使用 Promise 链

const asyncFunction = () => {
  api.fetchObjects()
    .then((result) => {
      setObjects(objects => [
        ...objects, // <-- shallow copy previous state array
        result,     // <-- append new state
      ]);
    });
}

或使用async/await

const asyncFunction = async () => {
  const result = await api.fetchObjects();
  setObjects(objects => [
    ...objects, // <-- shallow copy previous state array
    result,     // <-- append new state
  ]);
}

根据 actual 状态形状和 result 值,您的实际状态更新功能可能看起来略有不同,具体取决于您的具体需求。