Usar el gancho useContext con React 16.8+ funciona bien. Puede crear un componente, usar el gancho y utilizar los valores de contexto sin ningún problema.
Lo que no estoy seguro es cómo aplicar cambios a los valores del proveedor de contexto.
1) ¿Es el gancho useContext estrictamente un medio para consumir los valores de contexto?
2) ¿Hay alguna forma recomendada, usando los ganchos React, para actualizar los valores del componente secundario, que luego activará la reproducción del componente para cualquier componente que use el gancho useContext con este contexto?
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>Cómo actualizar el contexto con ganchos se analiza en ¿Cómo evitar pasar las devoluciones de llamada? parte de las Preguntas Frecuentes de Hooks.
El argumento pasado a createContext solo será el valor predeterminado si el componente que usa useContext no tiene un Provider por encima de él más arriba en el árbol. En su lugar, podría crear un Provider que proporcione el style y la visibility , así como funciones para alternarlos.
Ejemplo
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>Puede usar este enfoque, sin importar cuántos componentes anidados tenga, funcionará bien.
// 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" }); };