immutability
Validates against mutating props, state, and other values that are 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 from useState.
Common Violations
Invalid
// ❌ Array push mutation
function Component() {
  const [items, setItems] = useState([1, 2, 3]);
  const addItem = () => {
    items.push(4); // Mutating!
    setItems(items); // Same reference, no re-render
  };
}
// ❌ Object property assignment
function Component() {
  const [user, setUser] = useState({name: 'Alice'});
  const updateName = () => {
    user.name = 'Bob'; // Mutating!
    setUser(user); // Same reference
  };
}
// ❌ Sort without spreading
function Component() {
  const [items, setItems] = useState([3, 1, 2]);
  const sortItems = () => {
    setItems(items.sort()); // sort mutates!
  };
}Valid
// ✅ Create new array
function Component() {
  const [items, setItems] = useState([1, 2, 3]);
  const addItem = () => {
    setItems([...items, 4]); // New array
  };
}
// ✅ Create new object
function Component() {
  const [user, setUser] = useState({name: 'Alice'});
  const updateName = () => {
    setUser({...user, name: 'Bob'}); // New object
  };
}Troubleshooting
I need to add items to an array
Mutating arrays with methods like push() won’t trigger re-renders:
// ❌ Wrong: Mutating the array
function 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 array
function 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
Mutating nested properties doesn’t trigger re-renders:
// ❌ Wrong: Mutating nested object
function 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 level
function UserProfile() {
  const [user, setUser] = useState({
    name: 'Alice',
    settings: {
      theme: 'light',
      notifications: true
    }
  });
  const toggleTheme = () => {
    setUser({
      ...user,
      settings: {
        ...user.settings,
        theme: 'dark'
      }
    });
  };
}