Context Vs Props in React
Tags: react, context
Published: 2020-08-12 22:43:01

In this blog we will discuss:
-What is the context?
-Pros of using context over props
-Cons of using context
-How to use context?
What is the context?
Context is universal centralized data for your application. It allows us to pass data and methods to the Components.

Pros:
If you are using props, and you have to pass data to the last Child component amongst multiple Nested Component. The data needs to be passed through every component in the tree using props. So every component needs to know about that props data even if it's not using it.
Context Solves this problem. You can set the context on top and all the components in the middle don’t have to know anything about it and the one down at the bottom can access it. It kind of fills the same need as redux.
Cons:
Context makes debugging difficult because it's difficult to figure out what caused the error when you cannot see the data in the child components that are not importing Context. Even when you are looking at the App Component and you know there is a problem in one of the properties of state, but you have to look at all the components which are Consuming it to figure out which one of them caused the problem. Use context only when you have to.
How to use context for your React application?
What we need to do is create a Component to create Context which will give us a Provider and a Consumer. We can wrap our Components inside of the Provider and it will provide the data passed inside of it to all the Components, which can be accessed via Consumer(s) using context.
Create a component call DataContext.js ( You can name it whatever you like )
// DataContext.js
import React from "react";
/**
 * This creates two components: The Provider Component and a Consumer Component.
 * The provider is going to make the data you pass in the Provider available everywhere underneath it and the consumer is going to read from the provider
 * These are dummy methods. They don't do anything You are just describing to React what they look like.
 */
const DataContext = React.createContext({
   name: 'John',
   age: '23'
   handleNameChange() {}
   handleAgeChange() {}
});
export const Provider = SearchContext.Provider;
export const Consumer = SearchContext.Consumer;
Let's create three components Home.js , Login.js and Register.js. Our directory structure will be like:
-src
 -component
   -Home.js
   -Login.js
   -DataContext
App.js
And our Components hierarchy will be :
App > Home.js > Login.js , Register.js
Now we will import the Provider into App.js. We define state and event handler methods here. Then we wrap all of our components into Provider and pass the state of App as its value.
The job of Provider will then be to read the state of the App and provide it to other components. It will also make the methods defined here available to all the Components wrapped inside of the Provider.
// App.js
import React, { Component } from 'react';
import { Provider } from "./component/DataContext";
import Home from "./component/Home";
class App extends Component {
constructor( props ) {
      super( props );
      this.state = {
         name: '',
         age: '',
         handleNameChange: this.handleNameChange
         handleAgeChange: this.handleAgeChange,
      }
   }
handleNameChange = ( event ) => {
      this.setState({
         name: event.target.value
      });
   };
handleAgeChange = ( event ) => {
      this.setState({
         age: event.target.value
      });
   };
render() {
    return (
      <div className="App">
      <Provider value={this.state}>
         <Home/>
      </Provider>
      </div>
    );
  }
}
export default App;
The Home.js which will be the parent of Login.js and Register.js
We don’t need to pass props in Home.js because context from Provide can be used in any component. So the Child Components Login and Register can directly use them
// Home.js
import React from 'react';
import Login from "./Login";
import Register from "./Register";
export default class Home extends React.Component {
render() {
return(
   <React.Fragment>
    <Login/>
    <Register/>
   </React.Fragment>
  );
 }
}
Now in we can wrap our Login.js content into <Consumer> and pass it inside context like so :
All the methods of App.js and the state will be available in context ( example context.handleNameChange, context.name etc ). So instead of using this or props, you can use context.
import React from 'react';
import {Consumer} from "./DataContext";
export default class Login extends React.Component {
render() {
      return(
         <Consumer>
            { context => (
               <div>
                  <label htmlFor="name">
                     Name
                     <input type="text" name="name" id="name" onChange={context.handleNameChange}/>
                     { context.name }
                  </label>
               </div>
            ) }
         </Consumer>
);
   }
}
We can do the same for Register.js as well.
import React from 'react';
import { Consumer } from "./DataContext";
export default class Register extends React.Component {
render() {
  return(
    <Consumer>
     { context => (
      <div>
       <label htmlFor="age">
        Age
        <input type="text" name="age" id="age" onChange={context.handleAgeChange}/>
       </label>
      </div>
     ) }
    </Consumer>
  );
 }
}