我有一个用CRA引导的react应用程序,其中我使用@ reduxjs / toolkit库通过reduxjs实现了状态管理。该状态目前由4个不同的切片组成。
我现在的问题是,即使我更改了一个片的单个属性,通过useSelector钩子订阅了其他片的组件也会重新渲染,从而导致了我所做的各种奇怪的行为没想到。
通常,我从组件订阅切片的方式如下:
const slice1 = useSelector(({ slice1 }: RootState) => slice1)
其中RootState类型表示组成商店的所有切片,并结合如下的CombineReduce函数:
const rootReducer = combineReducers({
slice1: SliceOneReducer,
slice2: SliceTwoReducer,
...
})
我的印象是,在选择切片形式时使用解构状态可以避免在其他切片发生更改时重新渲染组件。
所以我的问题是:这是正确的行为还是我做事的方式错误?
编辑对于效果管理,由于我不太喜欢笨拙,我以以下方式添加了可观看redux的中间件:
const rootEpic: any = combineEpics(
...SliceOneEpics
)
然后在配置存储区时:
const epicMiddleware = createEpicMiddleware();
const store = configureStore({
reducer: reducers,
middleware: getDefaultMiddleware =>
getDefaultMiddleware().prepend(
epicMiddleware
)
})
epicMiddleware.run(rootEpic);
中间件会搞砸吗?也许以这种方式指定中间件会删除@ reduxjs / toolkit提供的immer的默认实现?
编辑2: 遵循Mary的评论,这基本上是导致所有其他片返回新对象的化约器。在这种情况下,特定的操作是setShowQRCode。但是其他任何行为的行为都相同。我直接更新状态是因为沉浸在幕后的魔幻之中
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
export interface UIState {
themeLoaded?: boolean,
layoutLoaded?: boolean,
showQrCode?: boolean,
showFloatingButton?: boolean,
moduleLoading?: boolean
}
const uiSlice = createSlice({
name: 'uistate',
initialState: {} as UIState,
reducers: {
setUIState(state: UIState, { payload }: PayloadAction<UIState>) {
Object.keys(payload).forEach(key => state[key] = payload[key])
},
setThemeLoaded(state: UIState, { payload }: PayloadAction<boolean>) {
state.themeLoaded = payload
},
setLayoutLoaded(state: UIState, { payload }: PayloadAction<boolean>) {
state.layoutLoaded = payload
},
setShowQRCode(state: UIState, { payload }: PayloadAction<boolean>) {
state.showQrCode = payload
}
}
})
export const { setUIState, setThemeLoaded, setLayoutLoaded, setShowQRCode } = uiSlice.actions
export default uiSlice.reducer