Как извлекать данные, а затем асинхронно выполнять другие задачи при загрузке с помощью useEffect (React JS)

#javascript #reactjs #react-hooks #fetch

#javascript #reactjs #реагирующие хуки #выборка

Вопрос:

Я изо всех сил пытаюсь понять, как это выполнить:

 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?

Комментарии:

1. Если оба этих состояния подключены к одному и тому же (набору) вызовов API, тогда их действительно должно быть только одно состояние.

Ответ №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 действия в перехватчике реакции, поэтому вам нужно извлечь свою функциональность за пределы перехватчика, а затем вызвать ее внутри перехватчика, а затем создать второй effect для запуска после stateOne обновления до состояния обновления 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 amp;amp; 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(); 
  })();
},[])
  

Комментарии:

1. Вы не можете запускать асинхронные действия непосредственно внутри перехвата react.