英文:
refactoring from createStore (Redux) to configureStore(RTK) leads to doubtfull situation or even error when enhancers are applied
问题
因为VS Code建议,我决定尝试重写现有的代码以使用configureStore。
重构之前(是的,reducer被采用"as it is",我知道应该使用combineReducers,但这时我只有一个reducer来处理整个状态):
declare module "@mui/styles/defaultTheme" {
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface DefaultTheme extends Theme {}
}
const composeEnhancers = process.env.NODE_ENV === "production" ? compose : composeWithDevTools({});
export const store = createStore(reducer, composeEnhancers(applyMiddleware(thunkMiddleware)));
const AppProvider: FC = ({ children }) => {
return (
<Provider store={store}>
<QueryClientProvider client={useQueryClient()}>
<StyledEngineProvider injectFirst>
<ThemeProvider theme={theme}>
<SnackbarProvider
maxSnack={3}
anchorOrigin={{
vertical: "bottom",
horizontal: "center",
}}
>
<PlaceContextProvider>
<CheckSupportForLocalStorage>
<CheckSupportForGeolocation>
<SetBackground>
<Router>{children}</Router>
</SetBackground>
</CheckSupportForGeolocation>
</CheckSupportForLocalStorage>
</PlaceContextProvider>
</SnackbarProvider>
</ThemeProvider>
</StyledEngineProvider>
</QueryClientProvider>
</Provider>
);
};
重构后,但不工作:
declare module "@mui/styles/defaultTheme" {
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface DefaultTheme extends Theme {}
}
const composeEnhancers = process.env.NODE_ENV === "production" ? compose : composeWithDevTools({});
export const store = configureStore({ reducer, enhancers: [composeEnhancers] });
const AppProvider: FC = ({ children }) => {
return (
<Provider store={store}>
<QueryClientProvider client={useQueryClient()}>
<StyledEngineProvider injectFirst>
<ThemeProvider theme={theme}>
<SnackbarProvider
maxSnack={3}
anchorOrigin={{
vertical: "bottom",
horizontal: "center",
}}
>
<PlaceContextProvider>
<CheckSupportForLocalStorage>
<CheckSupportForGeolocation>
<SetBackground>
<Router>{children}</Router>
</SetBackground>
</CheckSupportForGeolocation>
</CheckSupportForLocalStorage>
</PlaceContextProvider>
</SnackbarProvider>
</ThemeProvider>
</StyledEngineProvider>
</QueryClientProvider>
</Provider>
);
};
它能够编译,但会抛出运行时错误:"Uncaught Error: Expected the reducer to be a function." 我相信我按照这个模式操作:https://redux-toolkit.js.org/api/configureStore
像这样添加enhancers有什么问题?
英文:
because of VS Code suggestions, I decided to try to rewrite existing code to the one with configureStore.
Before refactor (yes, reducer is taken "as it is", I know that should use combineReducers; but at this time I have one reducer with whole state):
declare module "@mui/styles/defaultTheme" {
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface DefaultTheme extends Theme {}
}
const composeEnhancers = process.env.NODE_ENV === "production" ? compose : composeWithDevTools({});
export const store = createStore(reducer, composeEnhancers(applyMiddleware(thunkMiddleware)));
const AppProvider: FC = ({ children }) => {
return (
<Provider store={store}>
<QueryClientProvider client={useQueryClient()}>
<StyledEngineProvider injectFirst>
<ThemeProvider theme={theme}>
<SnackbarProvider
maxSnack={3}
anchorOrigin={{
vertical: "bottom",
horizontal: "center",
}}
>
<PlaceContextProvider>
<CheckSupportForLocalStorage>
<CheckSupportForGeolocation>
<SetBackground>
<Router>{children}</Router>
</SetBackground>
</CheckSupportForGeolocation>
</CheckSupportForLocalStorage>
</PlaceContextProvider>
</SnackbarProvider>
</ThemeProvider>
</StyledEngineProvider>
</QueryClientProvider>
</Provider>
);
};
After refactor, not working
declare module "@mui/styles/defaultTheme" {
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface DefaultTheme extends Theme {}
}
const composeEnhancers = process.env.NODE_ENV === "production" ? compose : composeWithDevTools({});
export const store = configureStore({ reducer, enhancers:[composeEnhancers] });
const AppProvider: FC = ({ children }) => {
return (
<Provider store={store}>
<QueryClientProvider client={useQueryClient()}>
<StyledEngineProvider injectFirst>
<ThemeProvider theme={theme}>
<SnackbarProvider
maxSnack={3}
anchorOrigin={{
vertical: "bottom",
horizontal: "center",
}}
>
<PlaceContextProvider>
<CheckSupportForLocalStorage>
<CheckSupportForGeolocation>
<SetBackground>
<Router>{children}</Router>
</SetBackground>
</CheckSupportForGeolocation>
</CheckSupportForLocalStorage>
</PlaceContextProvider>
</SnackbarProvider>
</ThemeProvider>
</StyledEngineProvider>
</QueryClientProvider>
</Provider>
);
};
its compiles but throws runtime error:Uncaught Error: Expected the reducer to be a function. I believed I follow this pattern: https://redux-toolkit.js.org/api/configureStore
What is wrong with adding enhancers like this?
答案1
得分: 1
通常,devTools
和 thunk
是默认中间件的一部分 - 如果你想添加中间件,应该使用 middleware
选项,而不是 enhancers
选项。
所以在你的情况下,
export const store = configureStore({ reducer });
已经配置了 devTools
和 thunk
中间件,你不需要再做其他操作。
不幸的是,你展示的片段不是有效的JavaScript(缺少一个 ]
以便解释),而且你将一个 composeEnhancers
函数传递进了那个函数中,而不是一个增强器本身(通常也不应该使用数组符号,因为这会覆盖所有默认的增强器)。
如果没有展示导致此错误的真正代码,很难提供更多关于问题具体原因的反馈。
英文:
Generally, devTools and thunk
are part of the default middleware - and if you want to add middleware, you should do so using the middleware
option, not the enhancers
option.
So in your case,
export const store = configureStore({ reducer });
already has the devTools and the thunk middleware configured, nothing more to do on your side.
Unfortunately, the snippet you are showing up there is not valid JavaScript (missing a ]
to be interpretable), and you are passing a composeEnhancers
function, not an enhancer itself into that function (and should generally probably also not use the array notation, as that overwrites all the default enhancers).
Without showing the code that really caused this error, it's hard to give more feedback on what exactly is causing you problems there.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论