0

So i got a setState named items const [items, setItems] = React.useState([]);

My Items Array Structure

[{
  "id": "0.625240011345925",
  "item_name": "Item 23",
  "item_price": "23",
  "item_qty": "1"
}, {
  "id": "0.735657461482515",
  "item_name": "Item 4",
  "item_price": "30",
  "item_qty": "1"
}, {
  "id": "0.287635530963835",
  "item_name": "Item 2",
  "item_price": "56",
  "item_qty": "1"
}]

Main Function

    const AddItemToBill = (navigation) => {
    navigation.navigate('AddItemToBill', {
        onReturn: (itemArray) => {
            const array = itemArray;
            for (let i = 0; i < array.length; i++) {
                const element = array[i];
                setItems([...items, element]);
                console.log('Items: ' + JSON.stringify(array))
            }
        }, navigation
    })
};

Check issue in below Gif

enter image description here

newdevv2
  • 201
  • 3
  • 10

2 Answers2

1

React setState is asynchronous. Updated state is only available on the next render cycle. So adding multiple items in a for loop would only result in the last item being updated.

Rules of hooks - Don’t call Hooks inside loops, conditions, or nested functions. Instead, always use Hooks at the top level of your React function, before any early returns.

Correct way is to build a new intermediate array & update state once -

const array = itemArray;
const newState = []; // array to hold the final state
for (let i = 0; i < array.length; i++) {
    const element = array[i];
    // update the array for the final state
    // DO NOT UPDATE STATE HERE
    newState.push(element);
    console.log('Items: ' + JSON.stringify(array))
}
// update state ONCE outside forloop
setItems([...items, newState]);
A G
  • 21,087
  • 11
  • 87
  • 112
  • This is what being added to `setItems` `[[{"id":"0.625240011345925","item_name":"Item 23","item_price":"23","item_qty":"1"}]]` – newdevv2 Jun 03 '22 at 12:09
  • Please read the answer carefully. – A G Jun 03 '22 at 12:10
  • please check the edited question – newdevv2 Jun 03 '22 at 13:04
  • @newdevv2 I think this is the correct answer except for one thing: `setItems([...items, newState]);` this line is wrong and should be replaced with `setItems([...items, ...newState]);` with the spread operator in `newState` otherwise this will add a sub array into array. Am I right @Assem Gautam? – Giovanni Esposito Jun 03 '22 at 13:41
1

As you are looping for getting all the elements, you can just spread directly itemArray

 onReturn: (itemArray) => {
                setItems(prev => ([...prev, ...itemArray]));
            }

Also used prev and not items state directly as a safety that it will always be called with the last value of the array in case a user make two quick interactions in a row

Hagai Harari
  • 2,767
  • 3
  • 11
  • 23