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

使用Redux-Toolkit做主题切换全局状态时Store reducer无效错误求解

问题根源

你抛出的reducer无效错误,核心是combineReducers传入的对象里,存在没有有效reducer的属性:

  • 你配置的rootReducer里,data字段对应的是combineReducers({}),空对象传入combineReducers会返回无效的reducer,触发报错。
  • 另外themeSlice里定义了空的extraReducers对象,新版Redux Toolkit已经不推荐使用对象写法写extraReducers,空对象也可能在部分版本触发校验问题。

修复方案

第一步 修正Store配置

要么给data字段加对应的reducer,要么暂时删掉空的data字段,修改后代码如下:

import { combineReducers, configureStore } from '@reduxjs/toolkit';
import { TypedUseSelectorHook, useSelector } from 'react-redux';
import { themeUiReducer } from './ui/themeSlice';

export const rootReducer = combineReducers({
    // 如果暂时没有data相关的reducer,先删掉空的data配置,后续加了再放回来
    ui: combineReducers({
        theme: themeUiReducer
    }),
});
export const store = configureStore({
    reducer: rootReducer,
    // 你原来的middleware配置是冗余的,configureStore默认会返回getDefaultMiddleware的结果,不需要手动写
});

export type RootState = ReturnType<typeof store.getState>
export const useTypedSelector: TypedUseSelectorHook<RootState> = useSelector;

第二步 修正themeSlice的空extraReducers

把空的extraReducers删掉即可,没有额外异步reducer需求不需要保留这个字段:

import { createSlice, PayloadAction } from "@reduxjs/toolkit";

export interface IThemes {
    themeMode: boolean | undefined,
    useOs: boolean | undefined
}

const initialState: IThemes = {
    themeMode: false,
    useOs: false
}

const themeSlice = createSlice({
    name: 'themeUI',
    initialState: initialState,
    reducers: {
        setThemeMode: (state, action: PayloadAction<boolean | undefined>) => {
            state.themeMode = action.payload;
        },
        setUseOs: (state, action: PayloadAction<boolean | undefined>) => {
            state.useOs = action.payload;
        },
    }
})

export const { setThemeMode, setUseOs } = themeSlice.actions;
export const themeUiReducer = themeSlice.reducer;

第三步 优化App.tsx的状态读取(可选)

你现在还在使用本地的useState存主题状态,没有用到Redux的全局状态,修改成从全局store读取的话,后续在导航栏、页脚修改主题才能全局生效:

import React, { useCallback } from 'react';
import './App.css';
import Layout from './components/Layout';
import { Route, Switch } from 'react-router-dom';
import { ThemeProvider, createTheme, useMediaQuery, CssBaseline } from '@mui/material';
import ThemeSwitcher from './theme/themeSwitcher';
import { useDispatch } from 'react-redux';
import { setThemeMode, setUseOs } from './store/ui/themeSlice';
// 导入你封装的类型化useSelector
import { useTypedSelector } from './store';

function App() {
  const dispatch = useDispatch();
  // 从Redux全局状态读取主题配置
  const { themeMode, useOs } = useTypedSelector(state => state.ui.theme);
  // Get OS-level preference for dark mode
  const prefersDarkMode: boolean | undefined = useMediaQuery("(prefers-color-scheme: dark)");

  const activeDarkMode = useOs ? prefersDarkMode : themeMode;
  const themeOption = (b: boolean) => (b ? "dark" : "light");

  const theme = React.useMemo(
    () =>
      createTheme({
        palette: {
          mode: themeOption(activeDarkMode!)
        }
      }),
    [activeDarkMode]
  );

  const dispatchTheme = useCallback(
    (themeMode: boolean | undefined) => {
      if(themeMode === null)
        dispatch(setThemeMode(prefersDarkMode));
      else
        dispatch(setThemeMode(themeMode));
    },
    [dispatch, prefersDarkMode]
  );

  return (
    <ThemeProvider theme={theme}>
      <CssBaseline />
      <ThemeSwitcher useOs={false} themeChanger={dispatchTheme} />
      <Layout>
        <Switch>
          <Route />
          <Route />
          <Route />
        </Switch>
      </Layout>
    </ThemeProvider>
  );
}

export default App;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 05:36:06