
Immutability and Structural Sharing
React relies on reference equality to detect changes. Mutating state directly breaks this — React can’t see the change and skips the re-render. Structural sharing is how you update immutably without copying the entire state tree.
Why Immutability
// Bug: mutating state directly
const [items, setItems] = useState([{ id: 1, name: 'Apple' }]);
function updateItem(name) {
items[0].name = name; // mutates the existing array
setItems(items); // same reference — React bails out, no re-render
} React compares prevState === nextState. Same reference → equal → no render.
Correct Update Patterns
Create new references for changed parts only:
// Update a field in an object
setUser(prev => ({ ...prev, name: 'Alice' }));
// Add to an array
setItems(prev => [...prev, newItem]);
// Remove from an array
setItems(prev => prev.filter(item => item.id !== idToRemove));
// Update one item in an array
setItems(prev => prev.map(item =>
item.id === targetId ? { ...item, name: 'Updated' } : item
)); Structural Sharing
You don’t copy everything — only the parts that changed. Unchanged subtrees keep their original references.
const state = {
users: [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }],
settings: { theme: 'dark' },
};
// Update only user 1's name
const nextState = {
...state, // settings keeps the same reference
users: state.users.map(u =>
u.id === 1 ? { ...u, name: 'Alicia' } : u // user 2 keeps same reference
),
};
nextState.settings === state.settings; // true — reused
nextState.users[1] === state.users[1]; // true — reused Unchanged references allow React.memo and useMemo to skip re-renders for those subtrees.
Deep Nesting
Immutable updates on deeply nested state are verbose:
const next = {
...state,
a: {
...state.a,
b: {
...state.a.b,
value: 'new',
},
},
}; Use Immer to write mutable-looking code that produces immutable results:
import produce from 'immer';
const next = produce(state, draft => {
draft.a.b.value = 'new'; // Immer handles the copying
}); useImmer integrates this with useState directly.









