#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.