【问题标题】:Set useState hook in a async loop在异步循环中设置 useState 挂钩
【发布时间】:2020-04-19 11:57:27
【问题描述】:

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

    }

【问题讨论】:

  • 在不相关的注释上,您的 async 函数没有 await 表达式。你用then() 解决你的承诺。

标签: javascript reactjs asynchronous react-hooks


【解决方案1】:

useState 提供了一种在更新时使用先前状态的方法(就像使用类组件时的回调方法一样),可以试一试

        .then(res => {
            setDati(prevDati => ([...prevDati, res.data]));
            onChildSubmit(dati);

        })

【讨论】:

    【解决方案2】:

    问题是这里的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})
        }
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-04
      • 2021-03-10
      • 2018-09-15
      • 2019-05-12
      • 2020-05-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多