I don’t understand why the component Form does not re-render when i called setInfoArray by passing a new array created using the push method.
When i logged infoArray
after submitting the form, the array was updated but the component did not re-render.
This is the code:
import React, { useEffect, useState } from 'react'
import './../styles/Form.css'
const Form = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [infoArray, setInfoArray] = useState([]);
//this function will update infoArray
const addToArray = (e) => {
e.preventDefault();
const newArray = infoArray;
newArray.push({
email: email,
password: password
})
console.log("newArray:", newArray);
setInfoArray(newArray);
console.log(infoArray)
}
return (
<>
<form action="">
<div>
<label htmlFor="email" className='formLabel'>Email</label>
</div>
<input type="email" name="email" id="email" value={email} onChange={(e) => { setEmail(e.target.value) }} placeholder='enter email' required autoComplete='off' />
<div>
<label htmlFor="password" className='formLabel'>password</label>
</div>
<input type="password" name="password" value={password} onChange={(e) => { setPassword(e.target.value) }} id="password" placeholder='enter password' required />
<button type="submit" className='submitBtn' onClick={addToArray}>Login</button>
</form>
{/* display the previous entries */}
<div>
{infoArray.map((item, index) => {
return (
<div className='entry' key={index}>
<span>{item.email}</span>
<span>{item.password}</span>
</div>
)
})}
</div>
</>
)
}
export default Form
However it does work when i do this:
const addToArray = (e) => {
e.preventDefault();
const newArray = [...infoArray,{email:email,password:password}];
setInfoArray(newArray)
}
Can anyone explain why the first approach didn’t work and this one did?
2
Answers
I’d recommend spending some time with the
useState
documentation https://react.dev/reference/react/useStateYou should assume that you always need to use
setState
if you want your component to re-render. Don’t mutate an object instate
directly.React uses
Object.is()
to determine if you have updated the state value. By usingnewArray = infoArray; newArray.push()
, you are referencing the same object (in this case the arrayinfoArray
) – it is effectively the same as doinginfoArray.push(...); setInfoArray(infoArray)
, so it is not identified as changed.By creating a new array, and spreading, the arrays are different.
As the React docs say, avoid mutating directly instead:
https://react.dev/reference/react/useState#ive-updated-the-state-but-the-screen-doesnt-update