Validates against mutating props, state, and other values thatare immutable.
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 fromuseState.
Common Violations
Invalid
// ❌ Array push mutation
functionComponent(){
const[items,setItems] =useState([1,2,3]);
constaddItem =()=>{
items.push(4);// Mutating!
setItems(items);// Same reference, no re-render
};
}
// ❌ Object property assignment
functionComponent(){
const[user,setUser] =useState({name:'Alice'});
constupdateName =()=>{
user.name ='Bob';// Mutating!
setUser(user);// Same reference
};
}
// ❌ Sort without spreading
functionComponent(){
const[items,setItems] =useState([3,1,2]);
constsortItems =()=>{
setItems(items.sort());// sort mutates!
};
}Valid
// ✅ Create new array
functionComponent(){
const[items,setItems] =useState([1,2,3]);
constaddItem =()=>{
setItems([...items,4]);// New array
};
}
// ✅ Create new object
functionComponent(){
const[user,setUser] =useState({name:'Alice'});
constupdateName =()=>{
setUser({...user,name:'Bob'});// New object
};
}Troubleshooting
I need to add items to an array
Mutating arrays with methods likepush() won’t trigger re-renders:
// ❌ Wrong: Mutating the array
functionTodoList(){
const[todos,setTodos] =useState([]);
constaddTodo =(id,text)=>{
todos.push({id,text});
setTodos(todos);// Same array reference!
};
return(
<ul>
{todos.map(todo=><likey={todo.id}>{todo.text}</li>)}
</ul>
);
}Create a new array instead:
// ✅ Better: Create a new array
functionTodoList(){
const[todos,setTodos] =useState([]);
constaddTodo =(id,text)=>{
setTodos([...todos,{id,text}]);
// Or: setTodos(todos => [...todos, {id: Date.now(), text}])
};
return(
<ul>
{todos.map(todo=><likey={todo.id}>{todo.text}</li>)}
</ul>
);
}I need to update nested objects
Mutating nested properties doesn’t trigger re-renders:
// ❌ Wrong: Mutating nested object
functionUserProfile(){
const[user,setUser] =useState({
name:'Alice',
settings:{
theme:'light',
notifications:true
}
});
consttoggleTheme =()=>{
user.settings.theme ='dark';// Mutation!
setUser(user);// Same object reference
};
}Spread at each level that needs updating:
// ✅ Better: Create new objects at each level
functionUserProfile(){
const[user,setUser] =useState({
name:'Alice',
settings:{
theme:'light',
notifications:true
}
});
consttoggleTheme =()=>{
setUser({
...user,
settings:{
...user.settings,
theme:'dark'
}
});
};
}