skip to Main Content

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


  1. I’d recommend spending some time with the useState documentation https://react.dev/reference/react/useState

    You should assume that you always need to use setState if you want your component to re-render. Don’t mutate an object in state directly.

    Login or Signup to reply.
  2. React uses Object.is() to determine if you have updated the state value. By using newArray = infoArray; newArray.push(), you are referencing the same object (in this case the array infoArray) – it is effectively the same as doing infoArray.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

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search