React中勾选复选框报Cannot add property 0错误的解决求助
React复选框勾选报错:无法添加属性0,对象不可扩展
问题现象
勾选复选框时触发如下错误,无法正常添加权限项:
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)
相关代码片段
组件状态与初始化
const [formData, setFormData] = useState<RoleFormData>({ name: "", permissions: [], }); useEffect(() => { if (addRole) { setFormData({ name: addRole.name, permissions: addRole.permissions, }); } }, []);
复选框处理函数
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); };
Redux初始状态与Reducer
// 初始状态 const initialState: IRoles = { rolesList: [], permissionList: [], permissionsBySection: {} as PermissionsBySection, addRole: { roleId: 0, name: "", permissions: [], }, error: null, loading: false, }; // Reducer reducers: { resetRolesItem: () => initialState, updateAddRoles: (state, action: PayloadAction<UpdateAddRole>) => ({ ...state, addRole: { ...state.addRole, ...action.payload, }, }), },
问题原因
Redux状态通常会被设置为不可扩展/冻结(比如Redux Toolkit默认配置、使用Immer或自定义中间件),防止直接修改原状态。当你在useEffect中直接将addRole.permissions赋值给formData.permissions时,formData.permissions引用的是Redux中不可扩展的原数组。即使浅拷贝了formData对象,里面的permissions数组还是原引用,调用push操作时就会触发“对象不可扩展”的错误。
解决方案
1. 初始化时深拷贝权限数组
在useEffect中初始化formData时,对addRole.permissions进行拷贝,切断与Redux原数组的引用:
useEffect(() => { if (addRole) { setFormData({ name: addRole.name, // 浅拷贝数组,创建可扩展的新数组 permissions: [...addRole.permissions], // 若数组元素是对象,需拷贝每个对象: // permissions: addRole.permissions.map(perm => ({ ...perm })), }); } }, []);
2. 处理函数中使用不可变更新方式
修改handleCheckboxChange,通过创建新数组/对象的方式更新状态,避免直接修改原引用:
const handleCheckboxChange = ( permissionId: number, section: string, checkedValues: CheckboxValueType[] ) => { const name = checkedValues.length > 0 ? String(checkedValues[0]) : ""; setFormData(prevFormData => { const existingIndex = prevFormData.permissions.findIndex( per => per.permissionId === permissionId && per.section === section ); if (existingIndex !== -1) { // 更新已有权限项:创建新数组替换对应元素 const updatedPermissions = [...prevFormData.permissions]; updatedPermissions[existingIndex] = { ...updatedPermissions[existingIndex], name, }; return { ...prevFormData, permissions: updatedPermissions }; } else { // 添加新权限项:创建新数组追加元素 return { ...prevFormData, permissions: [...prevFormData.permissions, { permissionId, section, name }], }; } }); };
3. 确保Redux状态更新符合不可变性原则
确认Redux reducer中始终返回新的对象/数组,你的updateAddRoles已经做了浅拷贝,这部分是合规的。如果action.payload包含permissions,也要确保传入的是新数组而非原引用。
内容的提问来源于stack exchange,提问作者Shiva Giri
相关产品推荐
相关产品推荐

