【问题标题】:How to fetch data and then perform other tasks asynchronously on load with useEffect (React JS)如何使用useEffect(React JS)获取数据然后在加载时异步执行其他任务
【发布时间】:2020-11-06 16:34:34
【问题描述】:

我正在努力弄清楚如何执行此操作:

const [stateOne, setStateOne] = useState();
const [stateTwo, setStateTwo] = useState();

useEffect(() => {
  /* fetch data */

  setStateOne(); /* not before data is fetched */
  setStateTwo(); /* not before data is fetched and setStateOne is complete */
},[])

这在概念上是否正确,是否可以在 useEffect 中异步运行此类任务?

【问题讨论】:

  • 如果这两个状态都连接到同一个(一组)API 调用 - 那么它们实际上应该只是一个状态。

标签: javascript reactjs react-hooks fetch


【解决方案1】:

多种效果:

const [asyncA,setAsyncA] = useState();
const [asyncB,setAsyncB] = useState();


useEffect(() => {

  (async() => {
     setAsyncA(await apiCall());
  })();

 // on mount fetch your data - no dependencies
},[]);


useEffect(() => {
  if(!asyncA) return;
  
  (async() => {
     setAsyncB(await apiCall(asyncA));
  })();

  // when asyncA is ready, then get asyncB
},[asyncA]);

useEffect(() => {
  if(!asyncA || !asyncB) return;
  // both are ready, do something
},[asyncA,asyncB])


或者,只是一个效果中的异步函数:

useEffect(() => {

  (async() => {
     const first = await apiCallA();
     const second = await apiCallB(first);
  })();

},[]);

【讨论】:

    【解决方案2】:

    你不能在反应钩子中运行async动作,所以你需要在钩子之外提取你的功能,然后在钩子内调用它,然后创建第二个effectstateOne更新后运行更新状态 2。

    const fetchAction = async () => {
        await fetchData(...)/* fetch data */
    
        setStateOne(); /* not before data is fetched */
        
    
    
    }
    
    useEffect(() => {
       
    },[])
    
    useEffect(() => {
       setStateTwo(); 
    },[StateOne])
    

    【讨论】:

      【解决方案3】:

      这将使您了解如何使用useEffect

      const {useState, useEffect} = React;
      
      const App = () => {
          const [stateOne, setStateOne] = useState(null)
          const [stateTwo, setStateTwo] = useState(null)
      
          useEffect(() => {
             stateOne && call(setStateTwo); 
          },[stateOne])
          
          const call = setState => {
            let called = new Promise(resolve => {
              setTimeout(() => {
                resolve(true)
              }, 2000)
            })
            called.then(res => setState(res))
          }
          
          return (
            <div>
              <button onClick={() => call(setStateOne)}>make call</button>
              <pre>stateOne: {JSON.stringify(stateOne)}</pre>
              <pre>stateTwo: {JSON.stringify(stateTwo)}</pre>
            </div>
          )  
      }
      
      ReactDOM.render(
        <App />,
        document.getElementById("react")
      );
      <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
      <div id="react"></div>

      【讨论】:

        【解决方案4】:

        将 async/await 与直接箭头函数一起使用

        useEffect(() => {
          (async() => {
            /* fetch data */
           // await is holding process till you data is fetched
           const data = await fetchData()
           // then set data on state one
           await setStateOne(); 
           // then set data on state second
           setStateTwo(); 
          })();
        },[])
        

        【讨论】:

        • 您不能直接在反应钩子中运行异步操作。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-11-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-26
        • 1970-01-01
        • 2022-09-23
        相关资源
        最近更新 更多