# New React 16.3 Context API

**URL:** <https://forum.kirupa.com/t/new-react-16-3-context-api/637819>\
**Category:** web dev\
**Created:** [February 6, 2018, 11:20pm UTC](https://forum.kirupa.com/t/new-react-16-3-context-api/637819 "2018-02-06T23:20:22Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![senocular](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/senocular/32/7217_2.png) [@senocular](https://forum.kirupa.com/u/senocular)\
**Post date:** [February 6, 2018, 11:20pm UTC](https://forum.kirupa.com/t/new-react-16-3-context-api/637819/1 "2018-02-06T23:20:22Z")

</div>

Is it just me, or does the [new context API](https://github.com/reactjs/rfcs/blob/master/text/0002-new-version-of-context.md) defeat the ease and flexibility of the old [context](https://reactjs.org/docs/context.html)? Now I have to wrap users of context within a consumer component _and_ a wrapper function call which is tightly coupled to the provider. Why can’t I simply have a props-like data structure with an origin of arbitrary anscentry?

---

<div class="post-metadata">

**Author:** ![senocular](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/senocular/32/7217_2.png) [@senocular](https://forum.kirupa.com/u/senocular)\
**Post date:** [February 7, 2018, 1:03pm UTC](https://forum.kirupa.com/t/new-react-16-3-context-api/637819/2 "2018-02-07T13:03:41Z")

</div>

In defense of the new stuff, the “tight coupling” I referenced isn’t as bad as it may initially appear (at least to me). For example, I saw instances created via `createContext`, but in reality it’s a class factory and you can instance those classes to your little heart’s desire. In other words, consumers aren’t tied to a single provider that was created with `createContext`. The component hierarchy is, in fact, traversed to find the closest instance of a respective provider and uses that for a data source. You can create multiple providers and have consumers pull from any one of those depending on the parenting.

```auto
const { Provider, Consumer } = React.createContext();

function MyApp (props) {
  return <div>
    <Provider value="A">
      <MyComponent /> {/* renders A */}
    </Provider>
    <Provider value="B">
      <MyComponent /> {/* renders B */}
    </Provider>
  </div>;
}

function MyComponent (props) {
  return <Consumer>{ letter => letter }</Consumer>
}

```

This can give you the older style, “arbitrary” provider behavior assuming you only ever use the same provider/consumer classes. But that requirement still makes it more difficult since any redistributable components that may act as consumers since they have no implicit way of knowing what kind of provider is going to be used and thus won’t be able to implement a respective consumer, at least not unless explicitly given one. And at that point we’re back to passing props through children again. But at least it’s only through changes of responsibility.

```auto
// ... same MyApp ...

import { LetterRenderer } from 'letter-consumer-lib';

function MyComponent (props) {
  // LetterRenderer may use a consumer internally but
  // won't be linked to the provider in MyApp because
  // it didn't exist when LetterRenderer was defined

  // return <LetterRenderer />

  // instead pass the linked consumer to LetterRenderer

  return <LetterRenderer consumer={ Consumer } />
}

```

Where `LetterRenderer` might look something like:

```auto
export function LetterRenderer (props) {
  const Consumer = props.consumer;
  return <Consumer>{ letter => `Your letter is "${letter}"!` }</Consumer>
}

```

(though more likely, I guess, the `LetterRenderer` would take basic props - i.e. `letter` vs `consumer` - and transfer them into its own provider-consumer)

---

<div class="post-metadata">

**Author:** ![Wayne](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/wayne/32/16501_2.png) [@Wayne](https://forum.kirupa.com/u/Wayne)\
**Post date:** [March 17, 2018, 9:48pm UTC](https://forum.kirupa.com/t/new-react-16-3-context-api/637819/3 "2018-03-17T21:48:27Z")

</div>

Hi,

I was trying this out when using

> [@senocular](#):
>
> React.createContext()

But get an error that the method is not found on react create context. I’m downloading the latest react version from npm. Do you guys know why it is not in the latest react? From 16 and up.

---

<div class="post-metadata">

**Author:** ![kirupa](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/kirupa/32/11616_2.png) [@kirupa](https://forum.kirupa.com/u/kirupa)\
**Post date:** [March 17, 2018, 10:21pm UTC](https://forum.kirupa.com/t/new-react-16-3-context-api/637819/4 "2018-03-17T22:21:51Z")

</div>

Do you have React 16.3?

---

<div class="post-metadata">

**Author:** ![Wayne](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/wayne/32/16501_2.png) [@Wayne](https://forum.kirupa.com/u/Wayne)\
**Post date:** [March 18, 2018, 2:31pm UTC](https://forum.kirupa.com/t/new-react-16-3-context-api/637819/5 "2018-03-18T14:31:37Z")

</div>

I thought the following symbol on package.json ^ will download the latest version?

---

<div class="post-metadata">

**Author:** ![Wayne](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/wayne/32/16501_2.png) [@Wayne](https://forum.kirupa.com/u/Wayne)\
**Post date:** [March 18, 2018, 8:10pm UTC](https://forum.kirupa.com/t/new-react-16-3-context-api/637819/6 "2018-03-18T20:10:48Z")

</div>

do I have to specify 16.3? or will this get it for me ^16.0

---

<div class="post-metadata">

**Author:** ![kirupa](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/kirupa/32/11616_2.png) [@kirupa](https://forum.kirupa.com/u/kirupa)\
**Post date:** [March 18, 2018, 9:18pm UTC](https://forum.kirupa.com/t/new-react-16-3-context-api/637819/7 "2018-03-18T21:18:35Z")

</div>

Look in your `node_modules/react/cjs/react.development.js` file and see what version is printed in the comments at the top:

 ![image](https://canada1.discourse-cdn.com/flex011/uploads/kirupa/original/2X/d/d9b4c42a4584f5120556c1ddb9b6cec7d057bed6.png)

---

<div class="post-metadata">

**Author:** ![Wayne](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/wayne/32/16501_2.png) [@Wayne](https://forum.kirupa.com/u/Wayne)\
**Post date:** [March 19, 2018, 8:28am UTC](https://forum.kirupa.com/t/new-react-16-3-context-api/637819/8 "2018-03-19T08:28:07Z")

</div>

It says it’s 16.2 not 16.3. I cannot use the new contextt feature. In npm I cannot see version 16.3 either.

---

<div class="post-metadata">

**Author:** ![Wayne](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/wayne/32/16501_2.png) [@Wayne](https://forum.kirupa.com/u/Wayne)\
**Post date:** [March 19, 2018, 8:36am UTC](https://forum.kirupa.com/t/new-react-16-3-context-api/637819/9 "2018-03-19T08:36:56Z")

</div>

You need to download the following: 16.3.0-alpha.1

---

<div class="post-metadata">

**Author:** ![Wayne](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/wayne/32/16501_2.png) [@Wayne](https://forum.kirupa.com/u/Wayne)\
**Post date:** [March 21, 2018, 3:40pm UTC](https://forum.kirupa.com/t/new-react-16-3-context-api/637819/10 "2018-03-21T15:40:12Z")

</div>

So I managed to implement something with it specifically when you have many different files / components in files. It’s great I’m in love! When is the final release? Alpha got announced back in February already. I know they have fast release cycles.

---

<div class="post-metadata">

**Author:** ![Wayne](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/wayne/32/16501_2.png) [@Wayne](https://forum.kirupa.com/u/Wayne)\
**Post date:** [April 19, 2018, 8:35pm UTC](https://forum.kirupa.com/t/new-react-16-3-context-api/637819/11 "2018-04-19T20:35:21Z")

</div>

How can I share one context with mutiple components?  
I cannot bind this for the my Context. I want to avoid redux.  
One change is not effecting the other.

```
    import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';

import MyContextProvider from "./MyContextProvider"
import MyContextProvider2 from "./MyContextProvider2"

window.onload = function(){

  let MyContext = React.createContext();
  

  if(document.getElementById('root') != null && document.getElementById('root2') != null){

    ReactDOM.render( <MyContextProvider provider={MyContext.Provider}>
      <App consumer={MyContext.Consumer} />
    </MyContextProvider>, document.getElementById('root'));

    ReactDOM.render(<MyContextProvider2 provider={MyContext.Provider}>
      <App consumer={MyContext.Consumer} />
    </MyContextProvider2>, document.getElementById('root2'));

    registerServiceWorker();
  }
}
```

---

<div class="post-metadata">

**Author:** ![Wayne](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/wayne/32/16501_2.png) [@Wayne](https://forum.kirupa.com/u/Wayne)\
**Post date:** [April 19, 2018, 9:03pm UTC](https://forum.kirupa.com/t/new-react-16-3-context-api/637819/12 "2018-04-19T21:03:04Z")

</div>

I even tried with the same context import  
import { Consumer, Provider } from ‘./Context.js’;

where the context.js is

```
import { createContext } from 'react';
const { Provider, Consumer } = createContext();
export { Consumer, Provider };

```

The state is not being shared:

```
 ReactDOM.render( <MyContextProvider provider={Provider}>
      <App consumer={Consumer} />
    </MyContextProvider>, document.getElementById('root'));

    ReactDOM.render(<MyContextProvider provider={Provider}>
      <App consumer={Consumer} />
    </MyContextProvider>, document.getElementById('root2'));
```

---

<div class="post-metadata">

**Author:** ![Wayne](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/wayne/32/16501_2.png) [@Wayne](https://forum.kirupa.com/u/Wayne)\
**Post date:** [April 19, 2018, 9:39pm UTC](https://forum.kirupa.com/t/new-react-16-3-context-api/637819/13 "2018-04-19T21:39:22Z")

</div>

After reading this, I guess I need to use redux here. What do you guys think?

> Is it a Redux killer?
> 
> No. The new Context API has its limitations.
> 
> For example, it encourages the use of immutable or persistent data structures or strict comparison of context values which might prove difficult because many common data sources rely on mutation.
> 
> Another limitation is that the new Context API only allows for a Consumer to read values from a single Provider type, one consumer to one provider. Unlike the current API, which allows a Consumer to connect to multiple Providers.

---

<div class="post-metadata">

**Author:** ![senocular](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/senocular/32/7217_2.png) [@senocular](https://forum.kirupa.com/u/senocular)\
**Post date:** [April 19, 2018, 10:07pm UTC](https://forum.kirupa.com/t/new-react-16-3-context-api/637819/14 "2018-04-19T22:07:53Z")

</div>

Each provider will have its own distinct value. Consumers will look up the React dom hierarchy until it finds a matching provider and use its value.

If you have a single value you want to share, then you’d use one provider that wraps multiple consumers. If you have multiple renders targeting different DOM elements, you might want to use a portal to manage that while being able to keep your components within the same provider.

```auto
const { Provider, Consumer } = React.createContext();

function Root2 (props) {
  return ReactDOM.createPortal(
    props.children,
    document.getElementById('root2')
  );
}

ReactDOM.render(
  <Provider value="shared">
    <Consumer>{ value => <h1>{ `First Root ${value}` }</h1></Consumer>
    <Root2>
      <Consumer>{ value => <h1>{ `Second Root ${value}` }</h1></Consumer>
    </Root2>
  </Provider>,
  document.getElementById('root')
);

```

---

<div class="post-metadata">

**Author:** ![Wayne](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/wayne/32/16501_2.png) [@Wayne](https://forum.kirupa.com/u/Wayne)\
**Post date:** [April 23, 2018, 7:07am UTC](https://forum.kirupa.com/t/new-react-16-3-context-api/637819/15 "2018-04-23T07:07:22Z")

</div>

How would you get the context object into another consumer class outside of the render function? So that it can be used in other methods that call methods in the context from the consumer?

I want to grab the context to be used outside of the render function and I have set it on a method on load but don’t like the way it is done.

```
Return
<Consumer>
{(context) => (

 <input type=“Text” onLoad={ e => this.context = context} />
 
)}
<Consumer>

```

Where this.context is a variable in the consumer class that Uses the consumer. I think this is horrible.

---

<div class="post-metadata">

**Author:** ![Wayne](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/wayne/32/16501_2.png) [@Wayne](https://forum.kirupa.com/u/Wayne)\
**Post date:** [April 23, 2018, 9:39am UTC](https://forum.kirupa.com/t/new-react-16-3-context-api/637819/16 "2018-04-23T09:39:49Z")

</div>

Okay I tried to add a HOC and it worked like so 🙂  
Please review.

```
  import React, { Component } from 'react';
import { Consumer, Provider } from './Context.js';

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

class Factory extends Component {

  componentDidMount(){
  this.props.value.sayMyNameAgain("Millad");
  }

  render() {

    return (
      <Consumer>
      {(context) => (
         <React.Fragment>
           <p>Age: {context.state.age}</p>
           <p>Name: {context.state.name}</p>
           <button onClick={context.growAYearOlder}>🍰🍥🎂</button>
         </React.Fragment>
       )}
      </Consumer>
    );
  }
}

export default WithContext(Factory);

```

and then you can use it like

`export default withContext(ComponentName);`

---

<div class="post-metadata">

**Author:** ![senocular](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/senocular/32/7217_2.png) [@senocular](https://forum.kirupa.com/u/senocular)\
**Post date:** [April 23, 2018, 12:56pm UTC](https://forum.kirupa.com/t/new-react-16-3-context-api/637819/17 "2018-04-23T12:56:39Z")

</div>

I think you got the idea with `withContext`, though I’m not sure your code makes a lot of sense. Aren’t you trying to avoid having `<Consumer>` in Factory, converting it’s value into a prop by using `withContext`?

---

<div class="post-metadata">

**Author:** ![Wayne](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/wayne/32/16501_2.png) [@Wayne](https://forum.kirupa.com/u/Wayne)\
**Post date:** [April 23, 2018, 1:26pm UTC](https://forum.kirupa.com/t/new-react-16-3-context-api/637819/18 "2018-04-23T13:26:22Z")

</div>

Correct! I should remove Consumer from Factory.
