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

Material UI Slider结合Redux出现只读数组赋值错误求助

解决TypeError: Cannot assign to read only property '0' of object '[object Array]'问题

这个错误的核心原因是Redux Toolkit(RTK)的Immer库会冻结处理后的状态对象,而你的代码中让本地组件的数组和Redux状态数组共享了同一个引用,导致Material UI的Slider组件尝试修改这个已经被冻结的数组时触发只读属性错误。

问题分析

你的Filter组件里用useState维护了本地的range数组,在handleSubmit中直接把这个数组传递给filterUpdate action。RTK的createReducer使用Immer来处理状态更新,当你在reducer中直接赋值state.range = action.payload.range时,Redux会把这个数组标记为只读(冻结)。由于本地组件的range和Redux状态的range是同一个引用,之后Slider组件尝试修改这个数组(比如在用户拖动滑块时),就会触发只读属性的错误。

解决方案

你只需要打破这个引用共享,让Redux状态使用数组的副本即可,有两种简单的实现方式:

方式1:在dispatch前创建数组副本

修改Filter组件中的handleSubmit方法,传递给action的是数组的浅拷贝:

const handleSubmit = () => {
  let filterValues = {
    range: [...range], // 创建数组副本,切断引用
    modelSelected,
  };
  dispatch(filterUpdate(filterValues));
};

方式2:在reducer中创建数组副本

修改你的reducer代码,在赋值时创建新的数组:

const reducer = createReducer({
  range: [0,60],
  model: 'None'
}, {
  [filterUpdate]: (state, action) => {
    state.range = [...action.payload.range]; // 创建新数组,避免引用共享
    state.model = action.payload.modelSelected
  }
})

额外建议

如果之后你想让Slider直接和Redux状态同步(去掉本地useState),可以这样修改:

  • 从Redux获取range状态:const range = useSelector(state => state.filter.range)
  • 修改handleRange为直接dispatch action:const handleRange = (newValue) => dispatch(filterUpdate({ range: newValue, modelSelected }))
  • 去掉本地的useState和setRange

这样就完全依赖Redux维护状态,避免了本地状态和Redux状态的引用问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 07:47:33