Validates against mutating props, state, and other values that are immutable.
Rule Details
Section titled “Rule Details”A component’s props and state are immutable snapshots. Never mutate them directly. Instead, pass new props down, and use the setter function from useState.
Common Violations
Section titled “Common Violations”Invalid
Section titled “Invalid”// ❌ Array push mutationfunction Component() { const [items, setItems] = useState([1, 2, 3]);
const addItem = () => { items.push(4); // Mutating! setItems(items); // Same reference, no re-render };}
// ❌ Object property assignmentfunction Component() { const [user, setUser] = useState({name: 'Alice'});
const updateName = () => { user.name = 'Bob'; // Mutating! setUser(user); // Same reference };}
// ❌ Sort without spreadingfunction Component() { const [items, setItems] = useState([3, 1, 2]);
const sortItems = () => { setItems(items.sort()); // sort mutates! };}// ✅ Create new arrayfunction Component() { const [items, setItems] = useState([1, 2, 3]);
const addItem = () => { setItems([...items, 4]); // New array };}
// ✅ Create new objectfunction Component() { const [user, setUser] = useState({name: 'Alice'});
const updateName = () => { setUser({...user, name: 'Bob'}); // New object };}Troubleshooting
Section titled “Troubleshooting”I need to add items to an array
Section titled “I need to add items to an array”Mutating arrays with methods like push() won’t trigger re-renders:
// ❌ Wrong: Mutating the arrayfunction TodoList() { const [todos, setTodos] = useState([]);
const addTodo = (id, text) => { todos.push({id, text}); setTodos(todos); // Same array reference! };
return ( <ul> {todos.map(todo => <li key={todo.id}>{todo.text}</li>)} </ul> );}Create a new array instead:
// ✅ Better: Create a new arrayfunction TodoList() { const [todos, setTodos] = useState([]);
const addTodo = (id, text) => { setTodos([...todos, {id, text}]); // Or: setTodos(todos => [...todos, {id: Date.now(), text}]) };
return ( <ul> {todos.map(todo => <li key={todo.id}>{todo.text}</li>)} </ul> );}I need to update nested objects
Section titled “I need to update nested objects”Mutating nested properties doesn’t trigger re-renders:
// ❌ Wrong: Mutating nested objectfunction UserProfile() { const [user, setUser] = useState({ name: 'Alice', settings: { theme: 'light', notifications: true } });
const toggleTheme = () => { user.settings.theme = 'dark'; // Mutation! setUser(user); // Same object reference };}Spread at each level that needs updating:
// ✅ Better: Create new objects at each levelfunction UserProfile() { const [user, setUser] = useState({ name: 'Alice', settings: { theme: 'light', notifications: true } });
const toggleTheme = () => { setUser({ ...user, settings: { ...user.settings, theme: 'dark' } }); };}