You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript可变数组报错:TypeError: Attempted to assign to readonly property

问题分析与解决方案

错误根源

你遇到的TypeError: Attempted to assign to readonly property是因为Redux Saga中错误地将全局数组直接作为action传递,导致该数组被Redux标记为只读(Redux要求状态不可变,会对传入的状态对象/数组进行冻结处理),后续执行notes.push()时无法修改只读数组,触发报错。

关键问题出在Saga代码的yield put(all());——put方法仅用于分发标准Redux action对象,而非直接传递数组。这里的all()返回全局notes数组,直接传入put会导致Redux将该数组转为只读状态。


具体修复方案

1. 修正Redux Saga的action分发逻辑

将直接传递数组改为分发标准action,让Redux reducer负责状态更新:

function* workerSaveNote(action: any) {
    try {
        yield NoteService.save(action.payload);
        // 获取最新的笔记列表
        const latestNotes = yield NoteService.all();
        // 分发标准action更新Redux状态
        yield put({ type: 'SET_NOTES', payload: latestNotes });
    } catch(e) {
        console.error(e);
    }
}

2. 移除全局数组,改用Redux管理状态(推荐)

全局数组与Redux混合使用容易引发状态不一致问题,建议将notes完全交给Redux维护:

  • 添加Reducer:
const initialState = { notes: [] };

function notesReducer(state = initialState, action) {
    switch (action.type) {
        case 'SET_NOTES':
            return { ...state, notes: action.payload };
        default:
            return state;
    }
}
  • 业务代码中通过Selector获取状态:
// React项目示例(使用useSelector)
// const notes = useSelector(state => state.notes.notes);

3. 若必须保留全局数组,避免被Redux冻结

如果坚持使用全局数组,需确保它不会被Redux处理为只读:

  • 移除Saga中的put(all()),改为重新初始化数组:
function* workerSaveNote(action: any) {
    try {
        yield NoteService.save(action.payload);
        // 重新初始化数组,断开与可能被冻结的原数组的引用
        yield NoteService.initialize();
    } catch(e) {
        console.error(e);
    }
}
  • 同时修改initialize方法,创建新数组避免引用冻结对象:
const initialize = async() : Promise<Note[]> => {
    // 解构创建新数组,脱离原冻结数组的引用
    notes = [...(await NoteStore.all())];
    return notes;
}

内容的提问来源于stack exchange,提问作者Aftab Naveed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 04:54:15