Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

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):

const {useState, useCallback} = React;
function Example() {
    const [theArray, setTheArray] = useState([]);
    const addEntryClick = () => {
        setTheArray(oldArray => [...oldArray, `Entry ${oldArray.length}`]);
    return [
        <input type="button" onClick={addEntryClick} value="Add" />,
        <div>{theArray.map(entry =>
          <div>{entry}</div>
ReactDOM.render(
    <Example />,
    document.getElementById("root")
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.1/umd/react-dom.production.min.js"></script>

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:

const {useState, useCallback} = React;
function Example() {
    const [theArray, setTheArray] = useState([]);
    const addEntryClick = () => {
        setTheArray([...theArray, `Entry ${theArray.length}`]);
    return [
        <input type="button" onClick={addEntryClick} value="Add" />,
        <div>{theArray.map(entry =>
          <div>{entry}</div>
ReactDOM.render(
    <Example />,
    document.getElementById("root")
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.1/umd/react-dom.production.min.js"></script>
...and try setTheArray(currentArray => [...currentArray, newElement]) if the above does not work. Most likely in useEffect(...theArray..., []), it's important to realize that theArray is a constant, so functional updates are needed for values from future renders – Aprillion Aug 8, 2019 at 19:12 If the useEffect has an empty dependency list [], it will be executed only during the first render. So the value of theArray inside the effect will always be initialArray. In situations where setTheArray([...initialArray, newElement]) would not make sense, and when theArray constant will always equal to initialValue, then functional updates are needed. – Aprillion Aug 9, 2019 at 9:08 @Aprillion - I'm afraid I'm still not getting it, possibly being a bit dense. :-) Why would you need an effect with just the initial array value? (I mean, there may be an infrequent use case, but...) And even if you do, what does it have to do with the question? – T.J. Crowder Aug 9, 2019 at 10:36 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

Thank you for all the examples. The exact thing I was having an issue with was your Push element at end of object of arrays. I tried so many different things, but just couldn't cobble it together. – sdouble Jan 19, 2020 at 19:40 The use of prevState fixed my issue that only the last call was being applied on a simultaneous array concat and filter. – Henrique Bruno Dec 20, 2020 at 7:25 The problem is that setTheArray is not updating immediatly the array, inside component handleMethod you can't call theArray value. – assayag.org Feb 26, 2022 at 2:18

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]);

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.

Please do not post link-only answers. The link might be broken in the future. Instead, create a write-up of that article and make sure to actually answer the question. – BlackCetha Apr 9, 2020 at 14:43 trigger setName(names => [...names, "newval"]) onChange, and console.log(names) returns []. Why isn't updated right away? – assayag.org Feb 26, 2022 at 2:26
// 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

The deep cloning you mention, does it mean receive as objA. UseState and concat the objA with objB? Same as this link? gist.githubusercontent.com/kahsing/… – Luiey Aug 14, 2020 at 10:00

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]);

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;
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.