React ships in JavaScript strict mode, so assigning to a property that has been frozen or defined as non-writable (state, props, refs, DOM nodes) throws a TypeError. The fix is to treat data as immutable and avoid touching read-only descriptors.
JavaScript strict mode throws this TypeError whenever code tries to mutate a property whose descriptor has 'writable: false', or when the object was frozen via Object.freeze() or Object.defineProperty(). React bundles always use strict mode, and many dev builds freeze props, refs, or state objects to detect mutations early. Writing to those read-only slots therefore fails with this error, which most often points at props/state updates, RefObject.current assignments, or DOM properties that React expects you to treat as immutable.
Check the exact property reported by the error and log its descriptor to confirm it is not writable:
const descriptor = Object.getOwnPropertyDescriptor(targetObject, 'propertyName');
console.log(descriptor); // writable: false warns you that you cannot assignReact works best when state/props are treated as immutable. When you need to change nested data, create a shallow copy before calling the updater:
// BAD
user.address.city = 'Berlin';
setUser(user);
// GOOD
setUser(prev => ({
...prev,
address: { ...prev.address, city: 'Berlin' }
}));
// For arrays
setItems(prev => [...prev, newItem]);Libraries or dev-only safeguards freeze objects to catch accidental mutations. Create a mutable copy before changing them:
const mutable = { ...frozenObject };
mutable.name = 'Alice';
const deepCopy = structuredClone(frozenObject);
deepCopy.items.push('x');Use helper libraries such as Immer or lodash clonedeep when necessary, and never mutate the frozen value in-place.
In TypeScript, useRef returns a RefObject whose current is readonly. Cast to MutableRefObject or declare the ref type explicitly:
// BAD
const inputRef = useRef<HTMLInputElement>(null);
inputRef.current = otherElement; // compile-time error + runtime error if strict mode rejects it
// GOOD
const inputRef = useRef<HTMLInputElement | null>(null);
const mutableRef = inputRef as MutableRefObject<HTMLInputElement | null>;
mutableRef.current = otherElement;Or use a callback ref so React controls assignment without manual writes.
If you are authoring the object, define the property with writable: true:
Object.defineProperty(obj, 'name', {
value: 'Jane',
writable: true,
configurable: true
});If the property is frozen via Object.freeze(), create a new object instead of reusing the frozen reference.
Don't overwrite DOM APIs that are read-only in strict mode. Instead set individual properties:
// BAD
div.style = 'color: blue;'; // Strict mode turns this into a read-only assignment
// GOOD
div.style.cssText = 'color: blue;';
div.style.setProperty('font-size', '14px');React's style prop already maps to the proper setters.
Hooks such as React Hook Form expect you to hand them refs rather than editing the underlying objects yourself. If the library exposes a readonly ref:
register('field', { ref: refElement });
// avoid: refElement.current = anotherElement;Call the library API (setValue, register, etc.) instead of reassigning internal references.
StrictMode in React: React's StrictMode intentionally double-invokes renderers and mount lifecycles to reveal side effects, so once you mutate a frozen object the error appears almost immediately in development.
Dev-only Freezing: Redux Toolkit, Immer, and other libraries freeze state objects only in development. That is why the error might only show up locally even though production works: the read-only guard is removed for performance.
Immutable Updates Improve Performance: Immutable updates keep shallow equality checks fast and avoid confusing bugs. Embrace immutability helpers (spread, structuredClone, immer/produce) instead of mutating in place.
React Hook useCallback has a missing dependency: 'variable'. Either include it or remove the dependency array react-hooks/exhaustive-deps
React Hook useCallback has a missing dependency
Cannot use private fields in class components without TS support
Cannot use private fields in class components without TS support
Cannot destructure property 'xxx' of 'undefined'
Cannot destructure property of undefined when accessing props
useNavigate() may be used only in the context of a <Router> component.
useNavigate() may be used only in the context of a Router component
Cannot find module or its corresponding type declarations
How to fix "Cannot find module or type declarations" in Vite