Last updated: Mar 6, 2024
Reading timeยท5 min
The error "Cannot assign to read only property of object" occurs when we try
to change a property of an object that has been frozen or when a property has
been defined with Object.defineProperties()
.
To solve the error, create a copy of the object or array, or set the property
to writable
.
Here are 3 examples of how the error occurs.
// ๐๏ธ With OBJECTS ๐๏ธ const obj = { name: 'James', }; Object.freeze(obj); // โ๏ธ Error: Cannot assign to read only property 'name' of object '#<Object>' obj.name = 'Alice'; // ------------------------------------------------------ // ๐๏ธ With ARRAYS ๐๏ธ const arr = ['a', 'b', 'c']; Object.freeze(arr); // โ๏ธ Error: Cannot assign to read only property '0' of object '[object Array]' arr[0] = 'z'; // ------------------------------------------------------ // ๐๏ธ With Object.defineProperties() ๐๏ธ const obj2 = {}; Object.defineProperties(obj2, { country: { value: 'Germany', // ๐๏ธ must be set writable: true // writable: true, // ๐๏ธ uncomment this }, }); // โ๏ธ Error: Cannot assign to read only property 'country' of object '#<Object>' obj2.country = 'Austria';
The first two errors occur because the object or array has been frozen with the Object.freeze() method.
The most common causes of the error are:
writable
to true
when using Object.defineProperties
.A frozen object can no longer be changed but you can create a copy of the array or object and change the copy.
// โ With OBJECTS const obj = { name: 'James', }; Object.freeze(obj); const objCopy = {...obj}; // ๐๏ธ create copy objCopy.name = 'Alice'; console.log(objCopy); // ๐๏ธ {name: 'Alice'} // -------------------------------------- // โ With ARRAYS const arr = ['a', 'b', 'c']; Object.freeze(arr); const arrCopy = [...arr]; // ๐๏ธ create copy arrCopy[0] = 'z'; console.log(arrCopy); // ๐๏ธ ['z', 'b', 'c']
We used the spread syntax (...) to create a copy of the object and the array, so we can change them.
The error also occurs when you try to sort a read-only array because the
Array.sort()
method sorts the array in place.
const arr = ['a', 'b', 'c']; Object.freeze(arr); // โ๏ธ TypeError: Cannot assign to read only property '0' of object '[object Array]' arr.sort();
To solve the error, create a copy of the array and sort the copy.
const arr = ['a', 'b', 'c']; Object.freeze(arr); // ๐๏ธ create copy const arrCopy = [...arr]; // ๐๏ธ sort the copy arrCopy.sort(); console.log(arrCopy); // ๐๏ธ [ 'a', 'b', 'c' ]
We used the spread syntax (...) to create a copy of the array and called the
sort()
method on the copy.
Now we no longer are trying to mutate a read-only array.
You can also use the Array.slice()
method to create a shallow copy of the
frozen array.
const arr = ['a', 'b', 'c']; Object.freeze(arr); // ๐๏ธ create a shallow copy of the array const arrCopy = arr.slice(); arrCopy.sort(); console.log(arrCopy); // ๐๏ธ [ 'a', 'b', 'c' ]
When the slice()
method is called without any arguments, it returns a shallow
copy of the original array.
writable
to true
if using Object.defineProperties()
If you get the error when using the
Object.defineProperties()
method, set the property to writable
if you want to change its value.
const obj2 = {}; Object.defineProperties(obj2, { country: { value: 'Germany', writable: true, // ๐๏ธ set property to writable }, }); obj2.country = 'Austria'; console.log(obj2.country); // ๐๏ธ "Austria"
The country
property is set to writable
, so it can be changed.
writable
parameter defaults to false
when using the Object.defineProperties()
method.If you want to be able to change the value of a property, explicitly set
writable
to true
.
Other properties you may have to set on the object are configurable
and
enumerable
:
false
, the property cannot be deleted or changed. Defaults
to false
.true
, the property is iterated over in loops. Defaults to
false
.false
, the value of the property cannot be changedconst obj2 = {}; Object.defineProperties(obj2, { country: { value: 'Germany', writable: true, // ๐๏ธ set property to writable configurable: true, enumerable: true, }, }); console.log(obj2); obj2.country = 'Austria'; console.log(obj2.country); // ๐๏ธ "Austria"
We also set the enumerable
and configurable
properties to true
.
When configurable
is set to true
, the property can be deleted. The default
value of the property is false
.
When enumerable
is set to true
, the property is iterated over in loops.
The default value of the property is false
.
Object.freeze
methodIf you pass an object or an array to Object.freeze
, you can't:
The best way to get around this is to create a copy of the object or array and change the copy.
If you use some third-party library that has frozen a state
object or array,
chances are you aren't supposed to be mutating the state
object directly.
The library probably exports a method that should be used to change the state
.
When using libraries such as React.js, the state shouldn't be modified directly.
Instead, the library provides methods and hooks that can be used to change the state.
If objects you get from a library are marked as read-only, then that was done intentionally as they shouldn't be directly modified by the user.
Here are guides on how to change a state array or a state object when using React.js:
To solve the "Cannot assign to read only property of object" error:
writable
property to true
if you use Object.defineProperties
.