27

I am using the new React Context API and I need to get the Consumer data from the Context.Consumer variable and not using it inside the render method. Is there anyway that I can achieve this?

For examplify what I want:

console.log(Context.Consumer.value);

What I tested so far: the above example, tested Context.Consumer currentValue and other variables that Context Consumer has, tried to execute Context.Consumer() as a function and none worked.

Any ideas?

Shubham Khatri
  • 211,155
  • 45
  • 305
  • 318
Gustavo Mendonça
  • 1,545
  • 3
  • 13
  • 22
  • I tested a similar approach, there's a `_currentValue` and `_defaultValue` members inside a consumer, but accessing `Context.Consumer._currentValue.value` always returns the default value or undefined if not properly inited. – keul Jun 06 '18 at 10:06
  • 2
    I create a HOC https://www.npmjs.com/package/react-context-consumer-hoc that achieves this by wrapping your component prior to exporting it. It might NOT be what you are looking for, but I want to put it here because this is where I ended up the first time I had this issue. – pgarciacamou Jun 22 '18 at 18:19

5 Answers5

30

Update

As of React v16.6.0, you can use the context API like:

class App extends React.Component {
    componentDidMount() {
       console.log(this.context);
    }
    render() {
       // render part here
       // use context with this.context
    }
}
App.contextType = CustomContext

However, the component can only access a single context. In order to use multiple context values, use the render prop pattern. More about Class.contextType.

If you are using the experimental public class fields syntax, you can use a static class field to initialize your contextType:

class MyClass extends React.Component {
  static contextType = MyContext;
  render() {
    let value = this.context;
    /* render something based on the value */
  }
}

Render Prop Pattern

When what I understand from the question, to use context inside your component but outside of the render, create a HOC to wrap the component:

const WithContext = (Component) => {
  return (props) => (
      <CustomContext.Consumer>
           {value =>  <Component {...props} value={value} />}
      </CustomContext.Consumer>
  )
}

and then use it:

class App extends React.Component {
    componentDidMount() {
       console.log(this.props.value);
    }
    render() {
       // render part here
    }
}
export default WithContext(App);
danronmoon
  • 3,613
  • 5
  • 32
  • 55
Shubham Khatri
  • 211,155
  • 45
  • 305
  • 318
  • 4
    This is more or less the official question from https://reactjs.org/docs/context.html#accessing-context-in-lifecycle-methods However I found this solution a lot complex and boilerplate than old `this.context` of React 15. – keul Jun 06 '18 at 09:41
  • 1
    @LucaFabbri, from version 16.6.0 version of React onwards, the context API can be used using `this.context` so no more BoilerPlate to it – Shubham Khatri Nov 23 '18 at 05:17
  • @ShubhamKhatri, I don't know why the 16.6+ `App.contextType = CustomContext`didn't work for me. It didn't make anything. And the `static contextType` only works when you have 1 context. However, the WithContext worked like a charm! Claps to you. – Aldo Apr 05 '19 at 13:32
  • @ShubhamKhatri, `static contextType = MyContext;` what's MyContext ? – Menai Ala Eddine - Aladdin May 02 '20 at 00:12
  • @MenaiAlaEddine MyContext is the context you create using React.createContext – Shubham Khatri May 02 '20 at 04:30
4

You can achieve this in functional components by with useContext Hook.

You just need to import the Context from the file you initialised it in. In this case, DBContext.

 const contextValue = useContext(DBContext);
Ankur Kedia
  • 1,895
  • 1
  • 7
  • 9
2

You can via an unsupported getter:

YourContext._currentValue

Note that it only works during render, not in an async function or other lifecycle events.

qwertzguy
  • 10,735
  • 5
  • 53
  • 59
0

This is how it can be achieved.

 class BasElement extends React.Component {
  componentDidMount() {
    console.log(this.props.context);
  }

  render() {
    return null;
  }
}

const Element = () => (
  <Context.Consumer>
    {context =>
      <BaseMapElement context={context} />
    }
  </Context.Consumer>
)
TN Yadav
  • 39
  • 5
0

For the @wertzguy solution to work, you need to be sure that your store is defined like this:

// store.js
import React from 'react';

let user = {};
const UserContext = React.createContext({
  user,
  setUser: () => null
});

export { UserContext };

Then you can do

import { UserContext } from 'store';

console.log(UserContext._currentValue.user);
Sebastien Horin
  • 8,814
  • 4
  • 39
  • 51