Suggest an editImprove this articleRefine the answer for “New object when updating state”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**React** does not track internal changes to objects; it determines whether the state has changed by the reference to the object. **Key point:** if you mutate the old object directly, React thinks the state hasn't changed and won't re-render the component.Shown above the full answer for quick recall.Answer (EN)Image## Short answer Because React **does not track internal changes to objects**; it **determines whether the state has changed** by the **reference to the object**. If you mutate (change) the old object directly, React thinks the state hasn't changed and won't re-render the component. --- ## 1. What happens when you do this: ```javascript const [user, setUser] = useState({ name: "Alex", age: 25 }); function updateName() { user.name = "Tim"; // mutating the object directly setUser(user); } ``` What React sees: - Old reference: 0xA12F - New reference: 0xA12F (the same, since the object was not recreated) - React compares the references and decides: "It's the same object, so there are no changes." Result: the component does not re-render; the UI stays old despite the data having changed. --- ## 2. The correct way: create a new object ```javascript setUser({ ...user, name: "Tim" }); ``` What happens now: - Old object -> 0xA12F - New object -> 0xB83C (same structure, but a different reference) - React compares the references and understands: "This is a new object, the component needs to be updated." The component re-renders, the UI updates. --- ## 3. Why React compares references, not values React uses a shallow comparison to determine whether the component needs to be updated: ```javascript oldState === newState ``` It doesn't do a deep comparison (deep equal); otherwise it would be too slow for large objects. That's why React determines a state change by a change in the reference (pointer). If the reference to the object changed, the state is new, and the UI is updated. --- ## 4. Example with an array The same principle applies to arrays: Bad: ```javascript items.push("new"); // mutating the array setItems(items); ``` Good: ```javascript setItems([...items, "new"]); // creating a new array ``` React sees the new reference to the array and updates the component. --- ## 5. Why mutation is also a logical error If you mutate the old state, then: - old references (in closures, hooks, props, effects) now point to changed data, which breaks predictability, - React may "think" the state is old and not trigger the necessary effects, - devtools and time-travel debugging become impossible (you can't "roll back" the state if it has been mutated). --- ## 6. A visual example ```javascript function UserCard() { const [user, setUser] = useState({ name: "Alex", age: 25 }); const handleClick = () => { // Direct mutation user.age++; setUser(user); // won't work }; const handleClickCorrect = () => { // Immutable update setUser(prev => ({ ...prev, age: prev.age + 1 })); }; console.log("Re-render:", user); return ( <> <p>{user.name} - {user.age}</p> <button onClick={handleClick}>Bad</button> <button onClick={handleClickCorrect}>Good</button> </> ); } ``` Clicking "Bad" won't cause React to re-render, while clicking "Good" will update the UI as expected. --- ## Summary | Behavior | Direct mutation | Copying ({ ...obj }) | |---|---|---| | Reference changes | No | Yes | | React sees the change | No | Yes | | Re-render happens | No | Yes | | Predictability | Breaks | Preserved | | DevTools / time travel support | Impossible | Possible | --- ### Final thought: > In React, state must be immutable. Always create a new object or array instead of changing the old one; that way React can correctly detect that the state has changed and update the interface.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.