2

I want to loop through an array, and call a function for each item, which does setState. I tried the following code:

const approveOrder = uniqueId => {
    if (approvedList.indexOf(uniqueId) < 0) {
        setApprovedList(approvedList.concat(uniqueId));
    }
};

const approveAllOrders = data => {
    data.forEach(dataItem => {
        approveOrder(dataItem.unique_id);
    });
};

But after the above function approveAllOrders, my list approvedList only contains one item, which is the last item of my data, which I passed to the function. I know that setState is not instant, that's why it is happening. So, what can I do to make my code work?

3 Answers 3

2

You should use a functional state update so that multiple enqueued updates correctly update from the previous state.

const approveOrder = uniqueId => {
  if (approvedList.indexOf(uniqueId) < 0) {
    setApprovedList(approvedList => approvedList.concat(uniqueId));
  }
};

Alternatively you can filter/map your data by id's not contained in the current state, and update state once.

const approveAllOrders = data => {
    const newDataIds = data.filter(dataItem => {
        return approvedList.indexOf(dataItem.unique_id) < 0;
    }).map(({ unique_id }) => unique_id);
    setApprovedList(approvedList => [...approvedList, newDataIds]);
};

or

const approveAllOrders = data => {
    const newDataIds = data.filter(dataItem => {
        return !approvedList.includes(dataItem.unique_id);
    }).map(({ unique_id }) => unique_id);
    setApprovedList(approvedList => [...approvedList, newDataIds]);
};
Sign up to request clarification or add additional context in comments.

Comments

1

You can first create a list of all the orders and then update the state. You don't need to have 2 functions to do this.

const approveAllOrders = data => {
    const orders = [];

    data.forEach(dataItem => {
       if (approvedList.indexOf(dataItem.unique_id) < 0) {
          orders.push(dataItem);
       }
    });

    setApprovedList([...approvedList, ...orders]);
};

Comments

0

you can also use reduce here.

const res = data.reduce( (res, dataItem) => {
   if(!res.includes(dataItem.unique_id)) {
       res.push(dataItem.unique_id)
   }
   return res
})

setApprovedList(res)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.