如何从另一个组件 React 更改 React Context 的值
how to change value of react Context from another component React
所以我试图通过反应上下文实现一个简单的主题切换,我需要根据另一个组件中的 onChange 事件更改上下文(ThemeProvider.jsx)提供者的值(ThemeSwitcher.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 事件进行更改。我无法想出将这两者联系起来的正确解决方案,因此非常感谢您的帮助。
我建议在 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
所以我试图通过反应上下文实现一个简单的主题切换,我需要根据另一个组件中的 onChange 事件更改上下文(ThemeProvider.jsx)提供者的值(ThemeSwitcher.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 事件进行更改。我无法想出将这两者联系起来的正确解决方案,因此非常感谢您的帮助。
我建议在 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