Reputation: 123
When I try to select a checkbox, it shows the error 'Cannot add property 0, the object is not extensible,' and I'm unable to add items properly. Can someone please help me with this?
const [formData, setFormData] = useState<RoleFormData>({
name: "",
permissions: [],
});
useEffect(() => {
if (addRole) {
setFormData({
name: addRole.name,
permissions: addRole.permissions,
});
}
}, []);
handling the checkbox
const handleCheckboxChange = (
permissionId: number,
section: string,
checkedValues: CheckboxValueType[]
) => {
const updatedFormData = { ...formData };
const permission = updatedFormData.permissions.find(
per => per.permissionId === permissionId && per.section === section
);
if (permission) {
permission.name =
checkedValues.length > 0 ? String(checkedValues[0]) : "";
} else {
updatedFormData.permissions.push({
permissionId,
section,
name: checkedValues.length > 0 ? String(checkedValues[0]) : "",
});
}
setFormData(updatedFormData);
};
rendering the checkbox dynamically and trying to update on form data
{Object.keys(permissionList).map(sectionKey => (
<Collapsible
title={permissionList[sectionKey][0]?.section}
isFirst={false}
key={sectionKey}
>
{permissionList[sectionKey]?.map((item, index) => (
<Checkbox.Group
options={[
{
label: item.name.toLowerCase(),
value: item.name.toLowerCase(),
},
]}
key={index}
value={formData.permissions
.filter(
per =>
per.section.toLowerCase() === item.section.toLowerCase()
)
.flatMap(per => per.name.toLowerCase())}
onChange={checkedValues =>
handleCheckboxChange(
item.permissionId,
item.section.toLowerCase(),
checkedValues
)
}
/>
))}
</Collapsible>
This is initial State in redux
const initialState: IRoles = {
rolesList: [],
permissionList: [],
permissionsBySection: {} as PermissionsBySection,
addRole: {
roleId: 0,
name: "",
permissions: [],
},
error: null,
loading: false,
};
This is Reducer
reducers: {
resetRolesItem: () => initialState,
// updateAddCoupon: (state, action: PayloadAction<UpdateAddCoupon>) => ({
// ...state,
// addCoupon: {
// ...state.addCoupon,
// ...action.payload,
// },
// }),
updateAddRoles: (state, action: PayloadAction<UpdateAddRole>) => ({
...state,
addRole: {
...state.addRole,
...action.payload,
},
}),
},
ERROR Cannot add property 0, object is not extensible TypeError: Cannot add property 0, object is not extensible at Array.push () at handleCheckboxChange (http://localhost:5173/src_pages_authorized_role_rolesDetail_index_tsx.d2f40c44ee046000e94a.hot-update.js:97:35) at onChange (http://localhost:5173/src_pages_authorized_role_rolesDetail_index_tsx.d2f40c44ee046000e94a.hot-update.js:188:24) at Object.toggleOption (http://localhost:5173/static/js/bundle.js:22699:57) at InternalCheckbox.checkboxProps.onChange (http://localhost:5173/static/js/bundle.js:22561:23) at handleChange (http://localhost:5173/static/js/bundle.js:59282:57) at HTMLUnknownElement.callCallback (http://localhost:5173/static/js/bundle.js:88407:18) at Object.invokeGuardedCallbackDev (http://localhost:5173/static/js/bundle.js:88451:20) at invokeGuardedCallback (http://localhost:5173/static/js/bundle.js:88508:35) at invokeGuardedCallbackAndCatchFirstError (http://localhost:5173/static/js/bundle.js:88522:29)
Upvotes: 2
Views: 144
Reputation: 203188
As far as I can tell you are updating a React state object. You should apply the Immutable Update pattern instead of mutating the references in the current state. You've made a shallow copy of the formData
state into updatedFormData
, but the handleCheckboxChange
handler is mutating the permissions
array by pushing directly into it or mutating the name
property of some specific permission object if it exists already.
Shallow copy all state, and nested state, that is being updated.
I suggest also using a Functional State Update to eliminate issues with updating from a stale closure over any state. This correctly updates from the previous state value.
Example:
const handleCheckboxChange = (
permissionId: number,
section: string,
checkedValues: CheckboxValueType[]
) => {
setFormData(formData => {
const permission = formData.permissions.some(
per => per.permissionId === permissionId && per.section === section
);
const name = checkedValues.length ? String(checkedValues[0]) : "";
if (permission) {
return {
...formData,
permissions: formData.permissions.map(per => {
if (per.permissionId === permissionId && per.section === section) {
return { ...per, name };
}
return per;
}),
};
} else {
return {
...formData,
permissions: formData.permissions.concat({
permissionId,
section,
name,
})
};
}
});
};
Upvotes: 0