2

According to the new context API documentation child components can either use consumer to access/modify the context or they can use the dynamic context to do the same, with consumer everything is working fine but i dont want to use the consumer approach, please check the example below

import React, { Component, createContext } from 'react';
import { render } from 'react-dom';

const Context = createContext({theme: 'light', changeTheme: ()=>{}});

class ThemedText extends Component{
  static contextType = Context;
  changeTheme(){
    //i want t do some logi specific to this class component then change the context value
    this.context.changeTheme('dark');
  }
  render(){
    return <div>The theme color is {this.context.theme} <button onClick={()=>{this.changeTheme()}}>Change</button></div>
  }
}

class ThemedTextWithConsumer extends Component{
  render(){
    return(
      <Context.Consumer>
      {({theme, changeTheme}) => (
          <div>Theme is {theme} (Consumer)  <button onClick={()=>{changeTheme('dark')}}>Change</button></div>
      )}
      </Context.Consumer>
    )
  }
}

class App extends Component{
  constructor(){
    this.state = {
      theme: 'light',
      changeTheme: this.changeTheme.bind(this)
    }
  }
  changeTheme(theme){
    this.setState({theme});
  }
  render(){
    return(
      <Context.Provider value={this.state}>
        <ThemedText/>
        <ThemedTextWithConsumer/>
      </Context.Provider>
    )
  }
}

the first component ThemedText is what i want to use since i need to execute some logic then trigger the changeTheme function from the context

Second component ThemedTextWithConsumer is working fine but as i understand i can only use the function from the context while inside the render function

How can i make the first component ThemedText work?

this is a working example on StackBlitz

Ahmed Farahat
  • 2,393
  • 2
  • 13
  • 25

1 Answers1

5

There are two issues in your StackBlitz demo.

First: You are using v16.5.0 for react whereas the new Context changes are pushed in 16.6.0 version of React. You must update the dependency versions first

Second: you aren't calling the function on click on button

Updated code:

class ThemedText extends Component{
  static contextType = Context;
  changeTheme(){
    //i want t do some logi specific to this class component then change the context value
    this.context.changeTheme('dark');
  }
  render(){
    return <div>The theme color is {this.context.theme} 
        <button onClick={()=>{
          // call the function here 
          this.changeTheme()
           }}
         >
             Change
         </button>
      </div>
  }
}

Working demo

If you are using version 16.3.0 to version prior to 16.6.0 then refer this answer on how to use context outside of render.

Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400