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
相关产品推荐
相关产品推荐

