Short answer
Do not change the object in place. Make a copy and change the copy: [...items].sort() instead of items.sort(), { ...user, name } instead of user.name = name. In Redux Toolkit, change state only inside a reducer, where Immer allows it. In React, never assign to props; lift the value into state in the parent and pass a setter down.
Why the object is read-only, and the fix
01
Sorting or changing Redux or Immer state outside a reducer
“Immer automatically freezes any state trees that are modified using produce.” Immer, Auto freezing
Redux Toolkit runs reducers through Immer, which freezes the state it returns. state.items.sort() in a component or a selector then throws, because sort() reorders the array in place. Sort a copy.
const items = useSelector((s) => s.todos.items); // wrong: sorts the frozen array in place items.sort(byDate); // right const sorted = [...items].sort(byDate);02
Changing a nested object you got from the store
“This protects against accidental modifications of the state tree outside of a producer.” Immer, Auto freezing
Assigning to state.user.name outside a reducer throws for the same reason. Dispatch an action and make the change in the reducer, where writing to the draft is allowed.
const userSlice = createSlice({ name: 'user', initialState: { name: '' }, reducers: { renamed(state, action) { state.name = action.payload; }, }, });03
Assigning to React props
“Props are read-only snapshots in time: every render receives a new version of props.” React, Passing Props to a Component
In development, React freezes the props object, so props.title = 'x' throws. In production it does not throw, but the change is not tracked: nothing re-renders because of it, and it is overwritten when the parent next passes new props. Keep the value in state in the parent and pass down a function to change it.
04
An object frozen on purpose
“This error happens only in strict mode code. In non-strict code, the assignment is silently ignored.” MDN, TypeError: "x" is read-only
Object.freeze(), a non-writable property from Object.defineProperty(), or a built-in such as Math.PI. Replace the whole object instead of changing one field. In non-strict scripts the same assignment does nothing without an error, which is why it can appear only after moving code into a module.
let config = Object.freeze({ theme: 'light' }); config = { ...config, theme: 'dark' };
Checked against the vendor’s docs on : MDN: TypeError: "x" is read-only; Immer docs: Auto freezing; React docs: Passing Props to a Component.
Rather hand it over?
Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.
- from $450App Fix TicketOne reproducible bug in an existing mobile or web app, diagnosed and fixed.See scope and start
- from $450AI-Built App RescueA Lovable, Bolt or Cursor app checked end to end in 3 days, then its worst problems fixed at a fixed price.No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.See scope and start
Related: React “Too many re-renders” · React “Maximum update depth exceeded” · “Cannot read properties of undefined”