如何从另一个组件 React 更改反应上下文的值

Posted

技术标签:

【中文标题】如何从另一个组件 React 更改反应上下文的值【英文标题】:how to change value of react Context from another component React 【发布时间】:2022-01-01 17:06:27 【问题描述】:

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

ThemeProvider.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;

ThemeSwitcher.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;

App.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;

如果需要,还有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;

如您所见,上下文的值应根据输入的 onChange 事件进行更改。我无法想出正确的解决方案来关联这两者,因此非常感谢您的帮助。

【问题讨论】:

【参考方案1】:

我建议在 ThemeProvider 组件中添加 useState() 钩子。 这是代码框: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;

然后你会像这样在需要的地方使用上下文:

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

【讨论】:

以上是关于如何从另一个组件 React 更改反应上下文的值的主要内容,如果未能解决你的问题,请参考以下文章

如何从另一个组件显示反应引导模式[重复]

反应钩子如何确定它们的组件?

React Context 和 Storybook:在组件故事中更改 React Context 的值

如何测试依赖于 useContext 钩子的反应组件?

在函数内反应 useEffect 陈旧值

React Context 组件在状态更改时不会更新