Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change the value of a Context with useContext?

Using the useContext hook with React 16.8+ works well. You can create a component, use the hook, and utilize the context values without any issues.

What I'm not certain about is how to apply changes to the Context Provider values.

1) Is the useContext hook strictly a means of consuming the context values?

2) Is there a recommended way, using React hooks, to update values from the child component, which will then trigger component re-rendering for any components using the useContext hook with this context?

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>
like image 767
Randy Burgess Avatar asked Feb 17 '19 23:02

Randy Burgess


People also ask

How do you change the value of useContext?

Using the useContext hook with React 16.8+ works well. You can create a component, use the hook, and utilize the context values without any issues.

How do you use useContext hooks?

Syntax: const authContext = useContext(initialValue); The useContext accepts the value provided by React. createContext and then re-render the component whenever its value changes but you can still optimize its performance by using memoization.

What does useContext return?

useContext. const value = useContext(MyContext); Accepts a context object (the value returned from React.createContext ) and returns the current context value for that context.


2 Answers

How to update context with hooks is discussed in the How to avoid passing callbacks down? part of the Hooks FAQ.

The argument passed to createContext will only be the default value if the component that uses useContext has no Provider above it further up the tree. You could instead create a Provider that supplies the style and visibility as well as functions to toggle them.

Example

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>
like image 141
Tholle Avatar answered Oct 03 '22 18:10

Tholle


You can use this approach, no matter how many nested components do you have it will work fine.

// 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" }); }; 
like image 22
mohamed khaled Avatar answered Oct 03 '22 17:10

mohamed khaled