1

This is the source code.

import React, { useState } from "react"
import ReactDOM from "react-dom"
import "./styles.css"

function App() {
  const [arr, setArr] = useState([1,2,3]) 
  return (
    <div className="App">     
      <h1>        
        Length:{arr.length}      
      </h1>   
      <h2>
        Values:
        {arr.map(i=>i+',')}
      </h2>

      <button
        onClick={() => {
          arr.push(0)    //my wrong code
          setArr(arr)    //my wrong code
          // setArr(prevValues => [...prevValues, 0])//Alex K's answer
          // setArr(prevArr => [...prevArr, prevArr.length + 1]); //rotemls98's answer
          // setArr([...arr,1])//venkateshwar's answer
          console.log(arr);
        }}
      >
        push
      </button>
    </div>
  );
}

const rootElement = document.getElementById("root")
ReactDOM.render(<App />, rootElement)

What I want to do is to push a new value into the current array and update length and values when I click the push button.
It printed to the console normally, but not change the display.
How to resolve this? enter image description here

Yuji
  • 371
  • 1
  • 6
  • 22

4 Answers4

3

react will not rerender if setState return the same state that was before. when you use the push method you mutate the state object. instead create a new array with the new item.

always update your state in immutable way.

in your case:

onClick={() => {
   setArr((prevArr) => ([...prevArr, prevArr.length + 1]));
}}
rotemls98
  • 187
  • 1
2

reference of new array is stored in old array variable

const [arr, setArr] = useState([1,2,3])
setArr([...arr,1])
L_J
  • 2,351
  • 10
  • 23
  • 28
venkateshwar
  • 39
  • 1
  • 3
1

I'm not too sure what values you want to push into your array, but the root cause of your issue is you're mutating the stateful array then attempting to update it (on lines 22 and 23).

Remove your arr.push(0) on line 22 and replace line 23 with:

setArr(prevValues => [...prevValues, 0])

and you will see the real time state update. In this example I just added 0 to the array for each button click, you can change that to whatever value you want to push into the array. Remember to never mutate a stateful array, hopefully that helps!

Alex K
  • 832
  • 4
  • 8
0

The setArr should contain an arrow function to access the prevState,so as to avoid incorrect / outdated state snapshot since react schedules State updates, it doesn't perform them instantly

const [arr, setArr] = useState([1,2,3]);
setArr(prevArr=>{
return [...prevArr,4]
});

if it is an object, and you want to change a single key's value.

const [userInput, setUserInput] = useState({
        enteredTitle: '',
        enteredAmount: '',
        enteredDate: ''
    });
setUserInput((prevUserInput)=>{
          return {
            ...prevUserInput,
            enteredTitle: "Something Else"
        }
})
//for copying the whole object, and only changing enteredTitle's value in it