How to change Context value while using React Hook of useContext

Randy Burgess picture Randy Burgess · Feb 18, 2019 · Viewed 33.6k times · Source

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?

Answer

Tholle picture Tholle · Feb 18, 2019

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>