HiveBrain v1.2.0
Get Started
← Back to all entries
snippetjavascriptreactCritical

How can I update React Context from inside a child component?

Submitted by: @import:stackoverflow-api··
0
Viewed 0 times
updatefromreactinsidecanchildhowcontextcomponent

Problem

I have the language settings in the context as like below:

class LanguageProvider extends Component {
  static childContextTypes = {
    langConfig: PropTypes.object,
  };

  getChildContext() {
    return { langConfig: 'en' };
  }

  render() {
    return this.props.children;
  }
}

export default LanguageProvider;


My application code will be something like below:


  
    
  


My Page is having a component to switch the language:


  


LanguageSwitcher in this MyPage needs to update the context to change the language into 'jp' as below:

class LanguageSwitcher extends Component {
  static contextTypes = {
    langConfig: PropTypes.object,
  };

  updateLanguage() {
    //Here I need to update the langConfig to 'jp'
  }

  render() {
    return Change Language;
  }
}

export default LanguageSwitcher;


How can I update the context from inside the LanguageSwitcher component?

Solution

Using hooks

Hooks were introduced in 16.8.0, so the following code requires a minimum version of 16.8.0 (scroll down for the class components example). CodeSandbox Demo
  1. Setting the parent state for dynamic context



Firstly, in order to have a dynamic context which can be passed to the consumers, I'll use the parent's state. This ensures that I've a single source of truth going forth. For example, my parent App will look like this:

const App = () => {
  const [language, setLanguage] = useState("en");
  const value = { language, setLanguage };

  return (
    ...
  );
};


The language is stored in the state. We will pass both language and the setter function setLanguage via context later.
  1. Creating a context



Next, I created a language context like this:

// Set the defaults
const LanguageContext = React.createContext({
  language: "en",
  setLanguage: () => {}
});


Here I'm setting the defaults for language ('en') and a setLanguage function which will be sent by the context provider to the consumer(s). These are only defaults and I'll provide their values when using the provider component in the parent App.

Note: the LanguageContext remains same whether you use hooks or class based components.
  1. Creating a context consumer



In order to have the language switcher set the language, it should have the access to the language setter function via context. It can look something like this:

const LanguageSwitcher = () => {
  const { language, setLanguage } = useContext(LanguageContext);
  return (
     setLanguage("jp")}>
      Switch Language (Current: {language})
    
  );
};


Here I'm just setting the language to 'jp', but you may have your own logic to set languages for this.
  1. Wrapping the consumer in a provider



Now I'll render my language switcher component in a LanguageContext.Provider and pass in the values which have to be sent via context to any level deeper. Here's how my parent App look like:

const App = () => {
  const [language, setLanguage] = useState("en");
  const value = { language, setLanguage };

  return (
    
      Current Language: {language}
      Click button to change to jp
      
        {/* Can be nested */}
        
      
    
  );
};


Now, whenever the language switcher is clicked it updates the context dynamically.

CodeSandbox Demo
Using class components

The latest context API was introduced in React 16.3, which provides a great way of having a dynamic context. The following code requires a minimum version of 16.3.0. CodeSandbox Demo.
  1. Setting the parent state for dynamic context



Firstly, in order to have a dynamic context which can be passed to the consumers, I'll use the parent's state. This ensures that I've a single source of truth going forth. For example, my parent App will look like this:

class App extends Component {
  setLanguage = language => {
    this.setState({ language });
  };

  state = {
    language: "en",
    setLanguage: this.setLanguage
  };

  ...
}


The language is stored in the state along with a language setter method, which you may keep outside the state tree.
  1. Creating a context



Next, I created a language context like this:

// Set the defaults
const LanguageContext = React.createContext({
  language: "en",
  setLanguage: () => {}
});


Here I'm setting the defaults for language ('en') and a setLanguage function which will be sent by the context provider to the consumer(s). These are only defaults and I'll provide their values when using the provider component in the parent App.
  1. Creating a context consumer



In order to have the language switcher set the language, it should have the access to the language setter function via context. It can look something like this:

class LanguageSwitcher extends Component {
  render() {
    return (
      
        {({ language, setLanguage }) => (
           setLanguage("jp")}>
            Switch Language (Current: {language})
          
        )}
      
    );
  }
}


Here I'm just setting the language to 'jp' but you may have your own logic to set languages for this.
  1. Wrapping the consumer in a provider



Now I'll render my language switcher component in a LanguageContext.Provider and pass in the values which have to be sent via context to any level deeper. Here's how my parent App look like:

class App extends Component {
  setLanguage = language => {
    this.setState({ language });
  };

  state = {
    language: "en",
    setLanguage: this.setLanguage
  };

  render() {
    return (
      
        Current Language: {this.state.language}
        Click button to change to jp
        
          {/* Can be nested */}
          
        
      
    );
  }
}


Now, whenever the language switcher is clicked it updates the context dynamically.

CodeSandbox Demo

Code Snippets

const App = () => {
  const [language, setLanguage] = useState("en");
  const value = { language, setLanguage };

  return (
    ...
  );
};
// Set the defaults
const LanguageContext = React.createContext({
  language: "en",
  setLanguage: () => {}
});
const LanguageSwitcher = () => {
  const { language, setLanguage } = useContext(LanguageContext);
  return (
    <button onClick={() => setLanguage("jp")}>
      Switch Language (Current: {language})
    </button>
  );
};
const App = () => {
  const [language, setLanguage] = useState("en");
  const value = { language, setLanguage };

  return (
    <LanguageContext.Provider value={value}>
      <h2>Current Language: {language}</h2>
      <p>Click button to change to jp</p>
      <div>
        {/* Can be nested */}
        <LanguageSwitcher />
      </div>
    </LanguageContext.Provider>
  );
};
class App extends Component {
  setLanguage = language => {
    this.setState({ language });
  };

  state = {
    language: "en",
    setLanguage: this.setLanguage
  };

  ...
}

Context

Stack Overflow Q#41030361, score: 738

Revisions (0)

No revisions yet.