16

I'm trying to update a UI using React Hooks and a form. I have a state set to monitor the value on the form and when I click submit, I want to add this value to an array (held in state) and display it on the UI. My problem is that when I submit the value, although it is added to the array (and state is updated), the UI only updates when I change the value in the input.

My Component is as follows:

const PushToArrayUpdateState = () => {

    const [array, setArray] = useState([]);
    const [formVal, setFormVal] = useState(``);

    const handleSubmit = event => {
        event.preventDefault();
        let updateArray = array;
        updateArray.push(formVal);
        console.log(updateArray);
        setArray(updateArray);
    };

    return (
        <div>
            <form onSubmit={handleSubmit}>
                <input type="text" name="arrayVal" onChange={e => setFormVal(e.target.value)} />
                <input type="submit" value="Submit" />
            </form>
            <div>
                {array.map((val, index) => <p key={index}>{val}</p>)}
            </div>
        </div>
    );
};

You can also see this [not] working at: https://codesandbox.io/s/p3n327zn3q

Has anyone got any suggestions as to why the setArray in the handleSubmit function is not automatically causing the component to re-render?

skyboyer
  • 19,620
  • 7
  • 50
  • 62
Ed Wright
  • 173
  • 1
  • 2
  • 5

2 Answers2

40

Instead of

let updateArray = array;

Try this:

const updateArray = [...array];

https://codesandbox.io/embed/qxk4k3zmzq

Because arrays in JS are reference values, so when you try to copy it using the = it will only copy the reference to the original array.

Roman Unt
  • 813
  • 6
  • 8
  • 1
    Dumb question but I can't figure out the right term to google, whats the "..." doing in [...array]. You answer was super helpful btw, thanks! – cwmacken Nov 03 '20 at 00:03
  • 2
    @cwmacken "Spread Operator" is what you're looking for. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax – Gates Dec 31 '20 at 17:39
3

A similar bug can happen with the same manifestation:

const [bought, setBought] = useState([])

...


bought.push(newItem)
setBought(bought)

To fix this you need to use

const newBought = [...bought, newItem] <- new reference
setBought(newBought) 
Mike Mackintosh
  • 13,530
  • 6
  • 58
  • 85
Tim Heilig
  • 31
  • 1