在异步循环中设置useState挂钩

时间:2019-12-30 19:24:21

标签: javascript reactjs asynchronous react-hooks

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

    }

2 个答案:

答案 0 :(得分:0)

问题在于,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})
    }
  }
}

答案 1 :(得分:0)

useState提供了一种在更新时使用先前状态的方式(就像在使用类组件时的回调方式一样),可能会导致失败

oid:=res.InsertedID.(primitive.ObjectID)
slice:=oid[:]
相关问题