一、Redux 做主题切换的适用场景
场景 | 原因 |
---|---|
多个页面共享 theme 状态 | Redux 全局 store 可随处访问 |
切换后需要联动多个组件更新 | 所有使用 theme 的组件都会响应变化 |
theme 还需要持久化(如 localStorage) | Redux 配合 middleware 比较方便实现 |
二、如何用 Redux 实现主题切换(完整步骤)
✅ 1. 定义 Redux slice(以 Redux Toolkit 为例)
// store/themeSlice.ts
import { createSlice } from '@reduxjs/toolkit';
const themeSlice = createSlice({
name: 'theme',
initialState: {
current: 'light', // or 'dark'
},
reducers: {
setTheme(state, action) {
state.current = action.payload;
},
toggleTheme(state) {
state.current = state.current === 'light' ? 'dark' : 'light';
},
},
});
export const { setTheme, toggleTheme } = themeSlice.actions;
export default themeSlice.reducer;
✅ 2. 将 themeReducer 加入到 Redux store
// store/index.ts
import { configureStore } from '@reduxjs/toolkit';
import themeReducer from './themeSlice';
export const store = configureStore({
reducer: {
theme: themeReducer,
// 其他 reducer...
},
});
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
✅ 3. 使用 useSelector
和 useDispatch
实现切换
// ThemeSwitcher.tsx
import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { toggleTheme } from './store/themeSlice';
import { RootState } from './store';
const ThemeSwitcher = () => {
const dispatch = useDispatch();
const theme = useSelector((state: RootState) => state.theme.current);
return (
<div>
<span>当前主题:{theme}</span>
<button onClick={() => dispatch(toggleTheme())}>切换主题</button>
</div>
);
};
✅ 4. 在 App 中读取 Redux 主题,应用到页面
// App.tsx
import React from 'react';
import { useSelector } from 'react-redux';
import { RootState } from './store';
function App() {
const theme = useSelector((state: RootState) => state.theme.current);
return (
<div className={`app-container theme-${theme}`}>
{/* rest content */}
</div>
);
}
搭配 CSS:
.theme-light {
--bg-color: #ffffff;
--text-color: #000;
}
.theme-dark {
--bg-color: #1e1e1e;
--text-color: #fff;
}
✅ 三、面试中你可以这样总结
“我们系统中采用 Redux 管理全局主题状态,切换主题后会自动通知所有订阅组件刷新样式,组件通过
useSelector
获取 theme 状态,页面统一使用theme-dark
/theme-light
类名控制样式变量。同时也支持持久化到 localStorage,下次打开时自动恢复。”
✅ 四、可选:配合 localStorage 实现持久化
你可以在 themeSlice
中扩展:
initialState: {
current: localStorage.getItem('theme') || 'light',
}
setTheme(state, action) {
state.current = action.payload;
localStorage.setItem('theme', action.payload);
}