如何从另一个 React 组件更改 React Context 的值

ali*_*our 6 javascript reactjs react-context

所以我试图通过反应上下文实现一个简单的主题切换,并且我需要根据另一个组件(ThemeSwitcher.jsx)中的 onChange 事件更改上下文(在 ThemeProvider.jsx 中)提供程序的值。

主题提供者.jsx:

import React, {createContext} from "react";
import {THEME_TYPE} from "../constants";

export const ThemeContext = createContext(THEME_TYPE.LIGHT);


const ThemeProvider = ({ children }) => {
    return <>
        <ThemeContext.Provider value={//THEME_TYPE.LIGHT or THEME_TYPE.DARK)}>
            {children}
        </ThemeContext.Provider>
    </>
};

export default ThemeProvider;
Run Code Online (Sandbox Code Playgroud)

主题切换器.jsx:

import React, {useContext} from "react";
import { THEME_TYPE } from "../constants";
import {ThemeContext} from "../providers/ThemeProvider";



const ThemeSwitcher = () => {
  const themeMode = useContext(ThemeContext);
  const handleThemeChange = (e) => {
     //value of context should change according to argument 'e'
  };

  return (
    <div className="switch-container">
      <label className="switch">
        <input
          data-testid="theme-changer"
          type="checkbox"
          checked={themeMode === THEME_TYPE.DARK}
          onChange={handleThemeChange}
        />
        <span className="slider round"></span>
      </label>
      <span className="text-color bold">Dark mode</span>
    </div>
  );
};

export default ThemeSwitcher;
Run Code Online (Sandbox Code Playgroud)

应用程序.jsx:

import React, {useContext} from "react";
import { Helmet } from "react-helmet";
import NameBox from "./components/NameBox";
import ThemeSwitcher from "./components/ThemeSwitcher";
import { THEME_TYPE } from "./constants";
import Styles from "./data/Styles";
import ThemeProvider from "./providers/ThemeProvider";
import {ThemeContext} from "./providers/ThemeProvider";


const StyleTag = () => {
    const themeMode = useContext(ThemeContext);
  return (
    <Helmet>
      <style>{Styles(themeMode)}</style>
    </Helmet>
  );
};

function App() {
  return (
    <ThemeProvider>
      <StyleTag />
      <NameBox />
      <ThemeSwitcher />
    </ThemeProvider>
  );
}

export default App;
Run Code Online (Sandbox Code Playgroud)

和 styles.js(如果需要):

import { THEME_TYPE } from "../constants";

const Theme = {
  [THEME_TYPE.LIGHT]: {
    background: "#fafafa",
    text: "#rgba(0, 0, 0, 0.87)",
    divider: "rgba(0, 0, 0, 0.12)",
  },
  [THEME_TYPE.DARK]: {
    background: "#303030",
    text: "#fff",
    divider: "rgba(255, 255, 255, 0.12)",
  },
};

const Styles = (theme) => `
body {background-color: ${Theme[theme].background};}
.text-color {color: ${Theme[theme].text};}
.box {border: 1px solid ${Theme[theme].divider}}
`;

export default Styles;
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,上下文的值应该根据输入 onChange 事件进行更改。我无法提出将这两者联系起来的正确解决方案,因此感谢您的帮助。

小智 6

我建议在 ThemeProvider 组件中添加 useState() 挂钩。这是codesandbox:https://codesandbox.io/s/magical-franklin-cril0 ?file=/src/ThemeProvider.jsx

代码如下所示:

import React, { createContext, useState } from "react";
import { THEME_TYPE } from "./constants";

export const ThemeContext = createContext(THEME_TYPE.LIGHT);

const ThemeProvider = ({ children }) => {
   const [themeType, setThemeType] = useState(THEME_TYPE.LIGHT);

   const changeTheme = (value) => {
      if (value) {
         setThemeType(THEME_TYPE.DARK);
      } else {
         setThemeType(THEME_TYPE.LIGHT);
      }
   };

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

export default ThemeProvider;
Run Code Online (Sandbox Code Playgroud)

然后你可以在需要的地方使用上下文,如下所示:

const themeMode = useContext(ThemeContext)
themeMode.themeType // THEME_TYPE.LIGHT or THEME_TYPE.DARK
themeMode.changeTheme(value) // if value is true, it would change to dark mode, if false to light mode
Run Code Online (Sandbox Code Playgroud)