Categories
React What I Learned Today

React: “Context API” – Great Stuff!

I’ve been playing around ( and having fun ) with react for a few weeks now. Building small projects here and there; including some mid-size ( whatever that means ) projects. The waterfall-flow of passing data ( props ) down to children-comments is awesome; a fairly easy concept to grasp.

I never thought that passing props down to other components could be such a tedious task…then I had a big project to complete, with multiple child-components down the stream-line. I spent so much time creating a path for a child component that was practically at the end of the stream-line; creating props for components that really shouldn’t have anything to do with the data being passed to it.

Then I came across the Context Api. The React team create this api to make the lives of a developer a lot easier. It gives you the ability to by-pass intermediate components so you can effectively provide data to whatever component you want…nice!

Don’t understand? No problem….let me break it down.

Let’s say you lived in New York and have a gift that you would like to give someone; who lives in California. You only have two options to deliver the gift:

Option A – A straight flight from New York To California

Option B – A flight that stops at every state from New York to California.

Now unless you have time on your hands and wanna do some sight-seeing, you will likely choose option – A; skipping all the intermediate states ( components ), and going straight to your desired destination.

Using the context Api is very simple: I’ll show you how with a straight forward example:

Lets say you have a statefull component ( your container ), :

class StatefullComponent extends React.Component {
	state = {
    	domain: 'RedEyeCoding',
      	tld: {
              com: '.com',
              org: '.org',
              net: '.net',
             },
        url: ''
    };
    render(){
      <React.Fragment>
        <h1> This is my App </h1>
        <ChildComponent1/> 
      </React.Fragment>  
    }
};

In the small app above we’re simply combining the domain and the TLD to make the full-url; only to then be used to update the state. Let us take a look at what things would look like if we decided to pass down props to each child: * will first begin by adding the props in the container to ChildComponent1*

Passed down to Child1

class ChildComponent1 extends React.Component {
..
.
    render(){
      return (
        <ChildComponent1
          propFromChild1={this.urlGenerator}/>) 
    }
};

Passed down to Child2

const childComponent2 = props => (
  	<ChildComponent3
      propFromChild2={props.propFromChild1} /> 
);

Down to Child3…

const childComponent3 = props => (
  	<ChildComponent4 
      propFromChild3={props.propFromChild2} /> 
);

…Down to Child4…

const childComponent4 = props => (
   	<ChildComponent5 
      propFromChild4={props.propFromChild3} /> 
);

Finally reaching Child5…

const childComponent5 = props => (
 
    <p>{props.propFromChild4}</p> 

);

I know, passing down props through 4 component s is not a lot. However, imagine having to pass it down through 10+ components:

<childComponent1/>
.
.
.
<childComponent14/>

😑…Not fun…😑

Context Api to the rescue!

Let’s get right to it; I will be using the dynamic approach since it is what I used in a recent project:

To start, what you need to do is create another, separate, component. Label it anything you want, but preferably something that will let you know that it is related to the context API: I’m gonna use “redEyeContext”.

First: import react, because, without, you have no context:

import React from 'react';

Then create your context. The ‘createContext’ method can accept objects as an argument:

import React from 'react';

               {/* New Component for Context */}

const RedEyeContext = React.createContext({
        domain: 'RedEyeCoding',
      	tld: {
              com: '.com',
              org: '.org',
              net: '.net',
             },
        url: ''            
 });

Now, we export this context:

import React from 'react';

{/* New Component for Context */}

{/* We're using the same exact state 
   from our statefull component */}
const RedEyeContext = React.createContext({
        domainContext: null,
      	tldContext: {
              comContext: null,
              orgContext: null,
              netContext: null,
             },
        urlContext: ''            
});

{/* Exporting  */}
export default RedEyeContext;

You probably noticed the value of null in the object i created. I also camelCased the word context for clarity. These default values do not matter, as it will be changed once we setup our provider…you’ll see.

The Provider

In order to provide state to your children, you will need to import the context into your container. You generally wouldn’t use the provider within a stateless component. Every context api comes with a provider component for you to provide your consumers access to the context.To provide access to the contents of the context to children, the provider utilizes the ‘value’ attribute to get this done; check out the example below.

So what is the provider? The provider is the one that will be initiating the state and sending that state down to any of the components that need them.So, we have a context file ready to go, now we should first determine who the provider should be. In our case it will be the parent element.

Lets start putting our context to use!

import RedEyeContext from './RedEyeContext';

class StatefullComponent extends React.Component {
	state = {
    	domain: 'RedEyeCoding',
      	tld: {
              com: '.com',
              org: '.org',
              net: '.net',
             },
        url: ''
    };
    render(){
      
      <RedEyeContext.Provider
        value={{
          domainContext: this.state.domain,
          tldContext: {
                comContext: this.state.tld['com'],
                orgContext: this.state.tld['org'],
                netContext: this.state.tld['net'],
               },
         urlContext: this.state.url
        }}>
        <h1> This is my App </h1>
        <ChildComponent1/> 
      </RedEyeContext.Provider>  
    }
};

So whats is happening in the code ,above?

Well, for starters, we’re importing our context api into our state-full component. Then we render the ChildComponent1 wrapped in the context api.

Remember those default values we setup the context file? Well notice anything? different in the in provider’s attributes? Yea, we’re setting values for the context’s object to the values of our current state; essentially giving all children access to the context; not just ChildComponent1.

The Consumer

Ok, so we covered the provider….then what about the consumer? …What’s the consumer do? As the name suggests, the consumer will component (child) that subscribes to the context provided by the provider ( <– doesn’t that sound funny? ).

Before we do, I would like to remind you of how many children we have; 5. Now, do we want to provide access to all 5? Nope, as that would defeat the purpose of using the context api.

Let’s say that we only wanted to provide access to child component3, how do we set that up?

Lets setup our consumer

import RedEyeContext from './RedEyeContext';

const childComponent3 = props => (
  <RedEyeContext.Consumer>
      {
        (context) => <ChildComponent4 
        	domain={context.domainContext}
            tld={context.tldContext}
            url={context.urlContext} />
      }
  <RedEyeContext.Consumer>
);

So whats happening above?

As we did with our provider, we need to, first, import the context api. Then we render whatever we want wrapped in the context api. Noticed something else? The information wrapped must be delivered using a function that returns your JSX code, otherwise it will not work.

That’s it! so if you have a pretty big application and don’t want to deal with passing props down through a bunch of children, react’s context api is your friend.

Hope this helps.