javascript - Set useState hook in a async loop - Stack Overflow

I'm new about reactJs.I'm trying to concatenate results in async loop, but something is wrong

I'm new about reactJs.

I'm trying to concatenate results in async loop, but something is wrong. setState not save correctly, when I print it I can see it's an empty array, I think because there is inside an async call.

How I can solve that? Please suggest me.

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('='+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 () {
            });
        }

    }

I'm new about reactJs.

I'm trying to concatenate results in async loop, but something is wrong. setState not save correctly, when I print it I can see it's an empty array, I think because there is inside an async call.

How I can solve that? Please suggest me.

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./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 () {
            });
        }

    }
Share Improve this question edited Dec 30, 2019 at 20:40 skyboyer 23.8k7 gold badges62 silver badges71 bronze badges asked Dec 30, 2019 at 19:24 MarcoMarco 1614 silver badges14 bronze badges 1
  • on an unrelated note, your async function has no await expression. You resolve your Promise with then() instead. – hotpink Commented Dec 30, 2019 at 19:52
Add a ment  | 

2 Answers 2

Reset to default 9

The problem is that useState here gives you the dati variable with a specific value. Then your asynchronous stuff happens, and setDati() is called multiple times, but dati is does not change until the form is re-rendered and you then call onFormSubmit again.

You have a few options.

You could add the results only once as an array.

const results = []

for(let i=0; i < daysDeparture.length; i++){
    dayDeparture = daysDeparture[i];
    const res = await axios.get('https://api.skypicker./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])

Or useReducer which reliably gives you the latest version of the state, right at the time that you change it, so you don't have stale data.

// 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./flights?flyFrom='+placeFrom+'&to='+placeTo+'&dateFrom='+dayDeparture+'&dateTo='+dayDeparture+'&partner=picky')
        dispatch({type: 'append', payload: res.data})
    }
  }
}

useState provides a way to use the previous state when updating (just like the callback way when you are using a class ponent), could give that a shot

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

        })

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744311734a4567981.html

相关推荐

  • javascript - Set useState hook in a async loop - Stack Overflow

    I'm new about reactJs.I'm trying to concatenate results in async loop, but something is wrong

    8天前
    40

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信