How to push element inside useState array React hook? Is that as an old method in react state? Or something new?
E.g. setState push example ?
When you use useState
, you can get an update method for the state item:
const [theArray, setTheArray] = useState(initialArray);
then, when you want to add a new element, you use that function and pass in the new array or a function that will create the new array. Normally the latter, since state updates are asynchronous and sometimes batched:
setTheArray(oldArray => [...oldArray, newElement]);
Sometimes you can get away without using that callback form, if you only update the array in handlers for certain specific user events like click
(but not like mousemove
):
setTheArray([...theArray, newElement]);
The events for which React ensures that rendering is flushed are the "discrete events" listed here.
Live Example (passing a callback into setTheArray
):
Because the only update to theArray
in there is the one in a click
event (one of the "discrete" events), I could get away with a direct update in addEntry
:
To expand a little further, here are some common examples. Starting with:
const [theArray, setTheArray] = useState(initialArray);
const [theObject, setTheObject] = useState(initialObject);
Push element at end of array
setTheArray(prevArray => [...prevArray, newValue])
Push/update element at end of object
setTheObject(prevState => ({ ...prevState, currentOrNewKey: newValue}));
Push/update element at end of array of objects
setTheArray(prevState => [...prevState, {currentOrNewKey: newValue}]);
Push element at end of object of arrays
let specificArrayInObject = theObject.array.slice();
specificArrayInObject.push(newValue);
const newObj = { ...theObject, [event.target.name]: specificArrayInObject };
theObject(newObj);
Here are some working examples too. https://codesandbox.io/s/reacthooks-push-r991u
The same way you do it with "normal" state in React class components.
example:
function App() {
const [state, setState] = useState([]);
return (
<div>
<p>You clicked {state.join(" and ")}</p>
//destructuring
<button onClick={() => setState([...state, "again"])}>Click me</button>
//old way
<button onClick={() => setState(state.concat("again"))}>Click me</button>
</div>
);
}
// Save search term state to React Hooks with spread operator and wrapper function
// Using .concat(), no wrapper function (not recommended)
setSearches(searches.concat(query))
// Using .concat(), wrapper function (recommended)
setSearches(searches => searches.concat(query))
// Spread operator, no wrapper function (not recommended)
setSearches([...searches, query])
// Spread operator, wrapper function (recommended)
setSearches(searches => [...searches, query])
https://medium.com/javascript-in-plain-english/how-to-add-to-an-array-in-react-state-3d08ddb2e1dc
Most recommended method is using wrapper function and spread operator together. For example, if you have initialized a state called name
like this,
const [names, setNames] = useState([])
You can push to this array like this,
setNames(names => [...names, newName])
Hope that helps.
You can append array of Data at the end of custom state:
const [vehicleData, setVehicleData] = React.useState<any[]>([]);
setVehicleData(old => [...old, ...newArrayData]);
For example, In below, you appear an example of axios:
useEffect(() => {
const fetchData = async () => {
const result = await axios(
{
url: `http://localhost:4000/api/vehicle?page=${page + 1}&pageSize=10`,
method: 'get',
}
);
setVehicleData(old => [...old, ...result.data.data]);
};
fetchData();
}, [page]);
setTheArray([...theArray, newElement]);
is the simplest answer but be careful for the mutation of items in theArray. Use deep cloning of array items.
if you want to push after specific index you can do as below:
const handleAddAfterIndex = index => {
setTheArray(oldItems => {
const copyItems = [...oldItems];
const finalItems = [];
for (let i = 0; i < copyItems.length; i += 1) {
if (i === index) {
finalItems.push(copyItems[i]);
finalItems.push(newItem);
} else {
finalItems.push(copyItems[i]);
}
}
return finalItems;
});
};
I tried the above methods for pushing an object into an array of objects in useState but had the following error when using TypeScript:
Type 'TxBacklog[] | undefined' must have a 'Symbol.iterator' method that returns an iterator.ts(2488)
The setup for the tsconfig.json was apparently right:
{
"compilerOptions": {
"target": "es6",
"lib": [
"dom",
"dom.iterable",
"esnext",
"es6",
],
This workaround solved the problem (my sample code):
Interface:
interface TxBacklog {
status: string,
txHash: string,
}
State variable:
const [txBacklog, setTxBacklog] = React.useState<TxBacklog[]>();
Push new object into array:
// Define new object to be added
const newTx = {
txHash: '0x368eb7269eb88ba86..',
status: 'pending'
};
// Push new object into array
(txBacklog)
? setTxBacklog(prevState => [ ...prevState!, newTx ])
: setTxBacklog([newTx]);