如何在现有的 React 站点上实现主题切换器

How to implement a theme switcher on an existing React site

我目前有两个主题文件,theme.jstheme-dark.js。我还有一个已经设置好的基于 React 的复杂站点,但我找不到一种方法来实现用户通过站点上的某个切换器在两个主题文件之间切换的方法。

这是我的 index.js 渲染函数的样子:

const rootElement = document.getElementById('root')
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  rootElement
)

App.tsx 文件中的相关代码如下所示:

<ThemeProvider theme={theme}>
     <CssBaseline />
     <SnackbarProvider
          .....
     </SnackbarProvider>
</ThemeProvider>

来自 App.tsx 文件的上述代码嵌套在一些自定义上下文提供程序组件中,并包含一些用于加载网站初始组件的数据。

我在使用现有代码实现主题切换器以在 theme.jstheme-dark.js 之间切换时遇到了一些问题。如果有人能推动我朝着正确的方向前进,我将不胜感激。不幸的是,由于我公司的安全原因,这是我可以粘贴的所有实际代码,但我认为这里的主要问题是 index.js 中的 <Provider> 元素在提供自定义主题提供程序时中断。

一个简单的状态就足够了,但您可能需要在应用程序深处切换状态,switch/button 所在的位置。

你可以通过Context,但是既然你已经在使用redux,为什么要重新发明轮子。

为您的主题类型创建一个 reducer,

// isDarkModeReducer.js

export default function isDarkModeReducer(state = false, action) {
  switch (action.type) {
    case 'toggleDarkMode': {
      return !state;
    }

   default: 
    return state;
  }
}

将其添加到您的 rootReducer

// rootReducer.js
...
import isDarkModeReducer from '<location of your isDarkModeReducer reducer>';
...
const rootReducer = combineReducers({
  ...
  isDarkMode: isDarkModeReducer
})
...

在您的 App.tsx 上从创建的商店访问 isDarkMode 值,并使用它有条件地传递 theme.jstheme-dark.js 文件。

// App.tsx
...
import theme from 'theme.js';
import theme-dark from 'theme-dark.js';
import { useSelector } from 'react-redux'

const isDarkMode = useSelector(state => state.isDarkMode);
...
return (
  <ThemeProvider theme={isDarkMode ? theme-dark : theme}>
     <CssBaseline />
     <SnackbarProvider
          .....
     </SnackbarProvider>
  </ThemeProvider>
);
...

对于切换,您所要做的就是 dispatch 从您的切换按钮所在的位置执行 toggleDarkMode 操作。

// SwitchButton
import { useDispatch } from 'react-redux'

const dispatch = useDispatch();

const toggleTheme = () => {
  dispatch({ type: 'toggleDarkMode' });
};


return (
  <button onClick={toggleTheme}>Switch Theme</button>
);

您可能还想将值保存到 localStorage 以进行持久化,您可以按照 docs.

中所述轻松地执行此操作