如何使用 useContext 更改 Context 的值?
How to change the value of a Context with useContext?
在 React 16.8+ 中使用 useContext
钩子效果很好。您可以毫无问题地创建组件、使用挂钩和使用上下文值。
我不确定的是如何将更改应用于上下文提供程序值。
1) useContext 挂钩严格来说是一种使用上下文值的方法吗?
2) 是否有推荐的方法,使用 React hooks 来更新子组件的值,然后将触发组件重新渲染使用此上下文的 useContext
hook 的任何组件?
const ThemeContext = React.createContext({
style: 'light',
visible: true
});
function Content() {
const { style, visible } = React.useContext(ThemeContext);
const handleClick = () => {
// change the context values to
// style: 'dark'
// visible: false
}
return (
<div>
<p>
The theme is <em>{style}</em> and state of visibility is
<em> {visible.toString()}</em>
</p>
<button onClick={handleClick}>Change Theme</button>
</div>
)
};
function App() {
return <Content />
};
const rootElement = document.getElementById('root');
ReactDOM.render(<App />, rootElement);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.2/umd/react-dom.production.min.js"></script>
Hooks FAQ 的 How to avoid passing callbacks down? 部分讨论了如何使用 hooks 更新上下文。
如果使用 useContext
的组件在树的上方没有 Provider
,则传递给 createContext
的参数只会是默认值。您可以创建一个 Provider
来提供 style
和 visibility
以及切换它们的功能。
例子
const { createContext, useContext, useState } = React;
const ThemeContext = createContext(null);
function Content() {
const { style, visible, toggleStyle, toggleVisible } = useContext(
ThemeContext
);
return (
<div>
<p>
The theme is <em>{style}</em> and state of visibility is
<em> {visible.toString()}</em>
</p>
<button onClick={toggleStyle}>Change Theme</button>
<button onClick={toggleVisible}>Change Visibility</button>
</div>
);
}
function App() {
const [style, setStyle] = useState("light");
const [visible, setVisible] = useState(true);
function toggleStyle() {
setStyle(style => (style === "light" ? "dark" : "light"));
}
function toggleVisible() {
setVisible(visible => !visible);
}
return (
<ThemeContext.Provider
value={{ style, visible, toggleStyle, toggleVisible }}
>
<Content />
</ThemeContext.Provider>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
您可以使用这种方法,无论您有多少嵌套组件都可以正常工作。
// Settings Context - src/context/Settings
import React, { useState } from "react";
const SettingsContext = React.createContext();
const defaultSettings = {
theme: "light",
};
export const SettingsProvider = ({ children, settings }) => {
const [currentSettings, setCurrentSettings] = useState(
settings || defaultSettings
);
const saveSettings = (values) => {
setCurrentSettings(values)
};
return (
<SettingsContext.Provider
value={{ settings: currentSettings, saveSettings }}
>
{children}
</SettingsContext.Provider>
);
};
export const SettingsConsumer = SettingsContext.Consumer;
export default SettingsContext;
// Settings Hook - src/hooks/useSettings
import { useContext } from "react";
import SettingsContext from "src/context/SettingsContext";
export default () => {
const context = useContext(SettingsContext);
return context;
};
// src/index
ReactDOM.render(
<SettingsProvider settings={settings}>
<App />
</SettingsProvider>,
document.getElementById("root")
);
// Any component do you want to toggle the theme from
// Example: src/components/Navbar
const { settings, saveSettings } = useSettings();
const handleToggleTheme = () => {
saveSettings({ theme: "light" });
};
在 React 16.8+ 中使用 useContext
钩子效果很好。您可以毫无问题地创建组件、使用挂钩和使用上下文值。
我不确定的是如何将更改应用于上下文提供程序值。
1) useContext 挂钩严格来说是一种使用上下文值的方法吗?
2) 是否有推荐的方法,使用 React hooks 来更新子组件的值,然后将触发组件重新渲染使用此上下文的 useContext
hook 的任何组件?
const ThemeContext = React.createContext({
style: 'light',
visible: true
});
function Content() {
const { style, visible } = React.useContext(ThemeContext);
const handleClick = () => {
// change the context values to
// style: 'dark'
// visible: false
}
return (
<div>
<p>
The theme is <em>{style}</em> and state of visibility is
<em> {visible.toString()}</em>
</p>
<button onClick={handleClick}>Change Theme</button>
</div>
)
};
function App() {
return <Content />
};
const rootElement = document.getElementById('root');
ReactDOM.render(<App />, rootElement);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.2/umd/react-dom.production.min.js"></script>
Hooks FAQ 的 How to avoid passing callbacks down? 部分讨论了如何使用 hooks 更新上下文。
如果使用 useContext
的组件在树的上方没有 Provider
,则传递给 createContext
的参数只会是默认值。您可以创建一个 Provider
来提供 style
和 visibility
以及切换它们的功能。
例子
const { createContext, useContext, useState } = React;
const ThemeContext = createContext(null);
function Content() {
const { style, visible, toggleStyle, toggleVisible } = useContext(
ThemeContext
);
return (
<div>
<p>
The theme is <em>{style}</em> and state of visibility is
<em> {visible.toString()}</em>
</p>
<button onClick={toggleStyle}>Change Theme</button>
<button onClick={toggleVisible}>Change Visibility</button>
</div>
);
}
function App() {
const [style, setStyle] = useState("light");
const [visible, setVisible] = useState(true);
function toggleStyle() {
setStyle(style => (style === "light" ? "dark" : "light"));
}
function toggleVisible() {
setVisible(visible => !visible);
}
return (
<ThemeContext.Provider
value={{ style, visible, toggleStyle, toggleVisible }}
>
<Content />
</ThemeContext.Provider>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
您可以使用这种方法,无论您有多少嵌套组件都可以正常工作。
// Settings Context - src/context/Settings
import React, { useState } from "react";
const SettingsContext = React.createContext();
const defaultSettings = {
theme: "light",
};
export const SettingsProvider = ({ children, settings }) => {
const [currentSettings, setCurrentSettings] = useState(
settings || defaultSettings
);
const saveSettings = (values) => {
setCurrentSettings(values)
};
return (
<SettingsContext.Provider
value={{ settings: currentSettings, saveSettings }}
>
{children}
</SettingsContext.Provider>
);
};
export const SettingsConsumer = SettingsContext.Consumer;
export default SettingsContext;
// Settings Hook - src/hooks/useSettings
import { useContext } from "react";
import SettingsContext from "src/context/SettingsContext";
export default () => {
const context = useContext(SettingsContext);
return context;
};
// src/index
ReactDOM.render(
<SettingsProvider settings={settings}>
<App />
</SettingsProvider>,
document.getElementById("root")
);
// Any component do you want to toggle the theme from
// Example: src/components/Navbar
const { settings, saveSettings } = useSettings();
const handleToggleTheme = () => {
saveSettings({ theme: "light" });
};