我对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);
})