Issue
- Using
Array.prototype.map is for mapping an existing array to a new array, not for issuing side-effects like updating React state or pushing into other array.
- When enqueuing state updates in a loop you must use a functional state update to correctly update from the previous state instead of the state from the previous render cycle.
Solution
const [values, setValues] = useState(["data1", "data2"]);
...
["data3", "data4", "data5"].forEach((item) => {
setValues(values => [...values, item]);
});
Since you are really just appending one array to the other you can make this simpler by removing the looping. (Well, you are still looping, but now the loop is within the state updater function so you avoid the state-looping issue)
setValues(values => [...values, ...["data3", "data4", "data5"]]);
or
setValues(values => values.concat(["data3", "data4", "data5"]));
UPDATE
Use the functional state update to shallow copy the previous values and map the new data to an array of just the second element and shallow copy that new result.
const newData = [
["data 1", "data 1.1"],
["data 2", "data 2.2"]
];
...
const [values, setValues] = useState(["data 1", "data 2"]);
...
setValues((values) => [
...values,
...newData.map(([, newValue]) => newValue) // *
]);
* newData is an array of arrays, [, newValue] in the callback uses destructuring assignment to "skip" the 0th element and assigns the 1th element to a variable newValue and returns this value for the mapping.
Edit
To remove duplicates created in new data, use a Set to remove them:
setValues((values) => [
...new Set([...values, ...newData.map(([, newValue]) => newValue)])
]);
Demo
