Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update the Context value in a Provider from the Consumer?

MyContext.js

import React from "react";  const MyContext = React.createContext('test'); export default MyContext; 

I created my context in a separated js file where I can access my parent as well as my child component

Parent.js

import MyContext from "./MyContext.js"; import Child from "./Child.js";  class Parent extends Component {      constructor(props) {       super(props);       this.state = {         Message: "Welcome React",         ReturnMessage:""       };     }          render() {         return (            <MyContext.Provider value={{state: this.state}}>                     <Child />             </MyContext.Provider>        )     } } 

So I created the parent component with a Provider context and calling child component in the provider tab

Child.js

import MyContext from "./MyContext.js";  class Child extends Component {      constructor(props) {       super(props);       this.state = {                 ReturnMessage:""       };     }          ClearData(context){         this.setState({            ReturnMessage:e.target.value         });         context.state.ReturnMessage = ReturnMessage     }      render() {         return (            <MyContext.Consumer>                                {(context) => <p>{context.state.Message}</p>}               <input onChange={this.ClearData(context)} />            </MyContext.Consumer>        )     } } 

So in child by using the Consumer, I can display the data in child rendering part.

I'm facing an issue when I want to update the state from the consumer.

How to update provider state or manipulate state of provider?

like image 251
Nowshad Syed Avatar asked May 24 '18 06:05

Nowshad Syed


People also ask

How do I change my context provider value?

To update a React Context from inside a child component, we can wrap the React Context provider around the child components. Then we set the value prop of the context provider to the the state setter function that lets us update the context value. Then we can use the useContext hook to access the context.

How do I use context outside my provider?

To access a React context outside of the render function, we can use the useContext hook. We create the UserContext by calling the React. createContext method with a default context value. Then in the Users component, we call the useContext hook with UserContext to accxess the current value of UserContext .

How do context providers pass multiple values?

To pass multiple values in React Context, we can use the Provider API. Also, we can easily consume the context data by utilizing the useContext React Hook. However, it is important to understand the basic syntax and approach behind this. To get a better idea, let us look at a simple example.


2 Answers

You could use the useContext hook to achieve this. It's quite easy to use it in the child elements of the Provider. As an example...

authContext.js

import { createContext } from "react";  const authContext = createContext({   authenticated: false,   setAuthenticated: (auth) => {} });  export default authContext; 

Login.js (component consuming the Context)

import React, { useContext } from "react"; import authContext from "./authContext";  export default () => {   const { setAuthenticated } = useContext(authContext);   const handleLogin = () => setAuthenticated(true);   const handleLogout = () => setAuthenticated(false);    return (     <React.Fragment>       <button onClick={handleLogin}>login</button>       <button onClick={handleLogout}>logout</button>     </React.Fragment>   ); }; 

Finally the index.js

import ReactDOM from "react-dom"; import React, { useState } from "react";  import authContext from "./authContext"; import Login from "./Login";  const App = () => {   const [authenticated, setAuthenticated] = useState(false);    return (     <authContext.Provider value={{ authenticated, setAuthenticated }}>       <div> user is {`${authenticated ? "" : "not"} authenticated`} </div>       <Login />     </authContext.Provider>   ); };  ReactDOM.render(<App />, document.getElementById("container")); 

As you can see, it becomes quite easy to consume the data stored in the context using the useContext hook. Of course, as with every React hook, it only works with functional components.

If you want to see the code working. https://codesandbox.io/s/react-playground-forked-wbqsh?file=/index.js

like image 57
Jacobo Jaramillo Avatar answered Sep 29 '22 16:09

Jacobo Jaramillo


Updating Context from a Nested Component

It is often necessary to update the context from a component that is nested somewhere deeply in the component tree. In this case you can pass a function down through the context to allow consumers to update the context:

theme-context.js

// Make sure the shape of the default value passed to // createContext matches the shape that the consumers expect! export const ThemeContext = React.createContext({   theme: themes.dark,   toggleTheme: () => {}, }); 

theme-toggler-button.js

import {ThemeContext} from './theme-context';  function ThemeTogglerButton() {   // The Theme Toggler Button receives not only the theme   // but also a toggleTheme function from the context   return (     <ThemeContext.Consumer>       {({theme, toggleTheme}) => (         <button           onClick={toggleTheme}           style={{backgroundColor: theme.background}}>           Toggle Theme         </button>       )}     </ThemeContext.Consumer>   ); }  export default ThemeTogglerButton; 

app.js

import {ThemeContext, themes} from './theme-context'; import ThemeTogglerButton from './theme-toggler-button';  class App extends React.Component {   constructor(props) {     super(props);      this.toggleTheme = () => {       this.setState(state => ({         theme:           state.theme === themes.dark             ? themes.light             : themes.dark,       }));     };      // State also contains the updater function so it will     // be passed down into the context provider     this.state = {       theme: themes.light,       toggleTheme: this.toggleTheme,     };   }    render() {     // The entire state is passed to the provider     return (       <ThemeContext.Provider value={this.state}>         <Content />       </ThemeContext.Provider>     );   } }  function Content() {   return (     <div>       <ThemeTogglerButton />     </div>   ); }  ReactDOM.render(<App />, document.root); 

The above example is straight from the React Context API docs v16.8.6, and is the recommended way to update a context value from a consumer. https://reactjs.org/docs/context.html#updating-context-from-a-nested-component

like image 21
Jack Vial Avatar answered Sep 29 '22 15:09

Jack Vial