[英]Why calling set function of useState hook applies immediately in async functions?
[英]Set useState hook in a async loop
我是 reactJs 的新手。
我试图在异步循环中连接结果,但出了点问题。 setState 没有正确保存,当我打印它时,我可以看到它是一个空数组,我想是因为里面有一个异步调用。
我该如何解决? 请建议我。
function App() {
const [data, setData] = useState({data:[]});
const handleChildSubmit = (data) => {
setData(data);
}
return (
<div>
<Form onChildSubmit={handleChildSubmit} />
<Results flights={data} />
</div>
);
}
const Form = ( {onChildSubmit} ) => {
const [dati, setDati] = useState([]);
const onFormSubmit = async (e) => {
e.preventDefault();
// Flights search Parameters
const data = new FormData(e.target);
const dateFrom = data.get('dateFrom');
const dateTo = data.get('dateTo');
const departureDay = data.get('day');
const placeFrom = data.get('placeFrom');
const placeTo = data.get('placeTo');
let dayDeparture;
const daysDeparture = getDayOfWeekArray(dateFrom,dateTo,departureDay);
// Loop of Fly Search in range time
for(let i=0; i < daysDeparture.length; i++){
dayDeparture = daysDeparture[i];
axios.get('https://api.skypicker.com/flights?flyFrom='+placeFrom+'&to='+placeTo+'&dateFrom='+dayDeparture+'&dateTo='+dayDeparture+'&partner=picky')
.then(res => {
setDati([...dati, res.data]);
onChildSubmit(dati);
})
.catch(function (error) {
console.log('error: '+error);
})
.finally(function () {
});
}
}
问题是, useState
这里给你dati
具有特定值的变量。 那么,你的异步的事情发生,并setDati()
被调用多次,但dati
是不会改变,直到形式重新呈现,你再调用onFormSubmit
一次。
你有几个选择。
您只能将结果作为数组添加一次。
const results = []
for(let i=0; i < daysDeparture.length; i++){
dayDeparture = daysDeparture[i];
const res = await axios.get('https://api.skypicker.com/flights?flyFrom='+placeFrom+'&to='+placeTo+'&dateFrom='+dayDeparture+'&dateTo='+dayDeparture+'&partner=picky');
results.push(res.data);
}
// Add all results when all are fetched.
setDati([...dati, ...results])
或者useReducer
可以在您更改状态时可靠地为您提供最新版本的状态,因此您没有过时的数据。
// Something like...
function reducer(state, action) {
switch(action.type) {
case 'append':
return [...state, action.payload]
}
}
function YourComponent() {
const [dati, dispatch] = useReducer(reducer, [])
const onFormSubmit = async (e) => {
for(let i=0; i < daysDeparture.length; i++){
dayDeparture = daysDeparture[i];
const res = await axios.get('https://api.skypicker.com/flights?flyFrom='+placeFrom+'&to='+placeTo+'&dateFrom='+dayDeparture+'&dateTo='+dayDeparture+'&partner=picky')
dispatch({type: 'append', payload: res.data})
}
}
}
useState 提供了一种在更新时使用先前状态的方法(就像使用类组件时的回调方式一样),可以试一试
.then(res => {
setDati(prevDati => ([...prevDati, res.data]));
onChildSubmit(dati);
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.