如何在React中用useContext切换明/暗主题

431 阅读2分钟

简介

这篇文章展示了一种使用React的useContextuseState 钩子来实现黑暗/光明模式切换的方法。相关文件是:src/ThemeProvider.tsx,src/index.tsx, 和src/App.tsx

这个项目使用了Typescript,但同样的功能也可以在javascript中通过移除类型来实现。

深入了解代码

ThemeProvider.tsx

在我们的ThemeProvider 组件中,我们将我们的Theme 定义为浅色或深色,我们将我们的ThemeContext 定义为一个具有两个属性的对象:themetoggleTheme (主题和切换主题的能力将通过useContext 钩子提供给其他组件)。

我们必须确保使用React.createContext ,导出我们创建的ThemeContext 对象。

ThemeProvider 组件中,我们使用useState 钩子维护我们的theme 状态,并创建一个toggleTheme 函数,在lightdark 之间切换状态。

为了简单起见,我们根据当前theme 的状态是亮还是暗,简单地设置文档主体的colorbackgroundColor 样式。最后,我们导出我们的ThemeContext Provider ,并将其值设置为与themetoggleTheme 属性的对象。然后我们在我们的ThemeContext.Provider 组件中渲染children

import React, { useState } from "react";
typescript;
type Theme = "light" | "dark";
type ThemeContext = { theme: Theme; toggleTheme: () => void };

export const ThemeContext = React.createContext<ThemeContext>(
  {} as ThemeContext
);

export const ThemeProvider: React.FC = ({ children }) => {
  const [theme, setTheme] = useState<Theme>("light");
  const toggleTheme = () => {
    setTheme(theme === "light" ? "dark" : "light");
  };

  const color = theme === "light" ? "#333" : "#FFF";
  const backgroundColor = theme === "light" ? "#FFF" : "#333";

  document.body.style.color = color;
  document.body.style.backgroundColor = backgroundColor;

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
};

index.tsx

在我们的index 文件中,我们简单地将整个应用程序包裹在我们新的ThemeProvider 组件中。当然,在实际项目中我们不需要在应用程序层面上这样做,我们只需要确保任何需要themetoggleTheme 的组件都在我们提供者的子树中。

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { ThemeProvider } from './ThemeProvider';

ReactDOM.render(
  <ThemeProvider>
    <App />
  </ThemeProvider>,
  document.getElementById('root')
);

App.tsx

App 组件中,我们使用useContext 钩子来访问我们的theme 字符串和toggleTheme 函数。我们创建了一个简单的按钮,可以切换主题,只使用theme 来决定我们向用户展示什么。"切换到黑暗模式 "或 "切换到光明模式"

import React, { useContext } from 'react';
import { ThemeContext } from './ThemeProvider';

const App: React.FC = () => {
  const { theme, toggleTheme } = useContext(ThemeContext);

  return (
    <div>
      <div>Hi friend!</div>
      <button onClick={toggleTheme}>
        Switch to {theme === 'light' ? 'dark' : 'light'} mode
      </button>
    </div>
  );
};

export default App;

就这样了!