Avoiding Prop Drilling in React Without Context API or Redux
Published: 2020-08-08 10:48:43

Prop Drilling is the process by which you pass data from one part of the React Component tree to another by going through other parts that do not need the data but only help in passing it around. 

Imagine someone living in Lagos, Nigeria placing an order on Amazon for a package. The package will have to go through many hands - it has to be flown by air to Nigeria, transported to the Lagos, moved from place to place until it gets into the hands of the buyer. At each stage, Amazon employs the services of people that do not 'care' about the product, they only help to 'pass' it to the person who really cared - the buyer.

Prop drilling is similar: You pass data (props) from  `Component1` to another `Component2` - which doesn't need the data to render but only passes it to another `Component3`, which also doesn't need it and may pass it to another `Component4`. This may continue until the data gets to the `ComponentNeedingProps`.

Consider the code snippet below:

```
import React from "react";
import "./styles.css";

export default function App() {
  return (
    <div className="App">
      <Component1 content="Who needs me?" />
    </div>
  );
}


function Component1({ content }) {
  return (
    <div>
      <h3>I am the first component</h3>;
      <Component2 content={content} />|
    </div>
  );
}

function Component2({ content }) {
  return (
    <div>
      <h3>I am the second component</h3>;
      <Component3 content={content} />
    </div>
  );
}

function Component3({ content }) {
  return (
    <div>
      <h3>I am the third component</h3>;
      <ComponentNeedingProps content={content} />
    </div>
  );
}

function ComponentNeedingProps({ content }) {
  return <h3>{content}</h3>;
}
```
The `content` prop is passed to `Component1` in the root component, `App`. But `Component1` does not need the prop to render, it only passes it to `Component2`, which passes it to `Component3`, which passes it to `ComponentNeedingProps`. It is this component that uses the `content` prop to render content in `<h3>{content}</h3>`. 


## Why is Prop Drilling a Problem?
Actually, prop drilling doesn't have to be a problem. If we are passing data only between 2 or 3 levels, we are fine. It will be easy to trace the flow of data. But imagine, we are drilling 5 levels...or 10 levels...or 15. 
Nah.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ietn60wo8v62se94m6ya.jpeg)



## How To Solve The Problem?
Prop drilling is not a new problem in react (quite obviously), and there have been many solutions that let us pass data down to deeply nested Components. 

One of which is Redux: You create a data `store` and `connect` any component to the `store` and voila, no matter where the component is positioned in the Component Tree it has access to the store.

React also has the concept of `Context` which lets you create something like a global `data store` and any Component in 'context' can have access to the data store. 

But...

These techniques can be expensive. For example, using React Context API, when the Context value changes it triggers a re-render in all the children reading from the Context (except you work around it). In fact, the official React documentation has this to say:

> If you only want to avoid passing some props through many levels, component composition is often a simpler solution than context

## How to Avoid Prop Drilling Using Component Composition
Component Composition is when you compose different Components, usually simple, together to create more complex functionality. If you have ever written a React app, I bet that you have been composing components. Take for example:

```
function LoginForm(props){
  return (
    <Input name="fname" />
    <Button onClick={props.handleClick} />)
}
```
Here, by using composition we are creating a 'complex' functionality, LoginForm by composing two simpler functionalities, Button and Input components. You can read more on the composition on React documentation page.

## What is the actual problem we are trying to solve?
The actual problem is that we want `ComponentNeedingProps` to be rendered in `ThirdComponent` but it needs data from the root component, `App` to do so. In other words, `ComponentNeedingProps` needs data from somewhere higher in the Component Tree (App) from where it is rendered (`ThirdComponent`).

The Solution?

## The untamed powers of the children prop
You can compose components by making one a child of another, for example:

``` 
<ReactComponent1>
  <ReactComponent2 />
</ReactCompoent1>
```

`ReactComponent2` is invoked inside of `ReactComponent1` and hence it is a child of it. Every component has an 'automatic' prop named children that holds the children of the Component. So in `ReactComponent1` we can write:

```
function ReactComponent1({ children }) {
  return 
   (<div> I render my children
      {children} 
   </div>)
}
```

How can we use it in this case? Remember we want ComponentNeedingProps to be rendered in another component down in the Component Tree, if we can pass ComponentNeedingProps as a child component with the data it needs and then render it in its parent then we have successfully avoided prop drilling.
So, we will have:

```
<ThirdComponent>
 <h3>I am the third component</h3>
     <ComponentNeedingProps content={content}  />
</ThirdCompoent>
```
And in the declaration of ThirdComponent we have:
```
function ThirdComponent({ children }) {
 return (
 <div>
    <h3>I am the third component</h3>
     {children}
   </div>
 );
}
```
This doesn't look much different from what we had earlier but wait for the magic.

By following this technique of rendering children, we can refactor App to this:
```
function App() {
const content = "Who needs me?";
return (
<div className="App">
  <FirstComponent>
    <SecondComponent>
      <ThirdComponent>
        <ComponentNeedingProps content={content}  />
      <ThirdComponent>
    </SecondComponent>
  </FirstComponent>
</div>
);
}
```
Then we refactor each of the other components to render their children

`FirstComponent`:
```
function FirstComponent({ children }) {
  return (
    <div>
      <h3>I am the first component</h3>;
     { children }
    </div>
  );
}
```

`SecondComponent`:
```
function SecondComponent({ children }) {
  return (
    <div>
      <h3>I am the second component</h3>;
     {children}
    </div>
  );
}
```
`ThirdComponent`:
```
function ThirdComponent({ children }) {
  return (
    <div>
      <h3>I am the third component</h3>
        {children}
    </div>
  );
}
```
`ComponentNeedingProps` stays as it is:
```
function ComponentNeedingProps({ content }) {
  return <h3>{content}</h3>
}
```

Did you see it? We have avoided prop drilling by giving `ComponentNeedingProps` the data it needs right from the source of the data App and then by using the children prop, we passed it down to where it should be rendered, `ThirdComponent`.
Awesome. See the complete code:
```
import React from "react";
import "./styles.css";

function FirstComponent({ children }) {
  return (
    <div>
      <h3>I am the first component</h3>;
     { children }
    </div>
  );
}

function SecondComponent({ children }) {
  return (
    <div>
      <h3>I am the second component</h3>;
     {children}
    </div>
  );
}

function ThirdComponent({ children }) {
  return (
    <div>
      <h3>I am the third component</h3>
        {children}
    </div>
  );
}

function ComponentNeedingProps({ content }) {
  return <h3>{content}</h3>
}

export default function App() {
  const content = "Who needs me?";
 return (
    <div className="App">
      <FirstComponent>
        <SecondComponent>
          <ThirdComponent>
            <ComponentNeedingProps content={content}  />
          </ThirdComponent>
        </SecondComponent>
      </FirstComponent>
    </div>
  );
}

```

# When should you use the Context API?

You can also use the Context API to avoid prop drilling and I may write another article on that in the nearest future.

If you need to have some data accessible by many components at different nesting levels, then you should use the Context API. React docs advises that we 'apply it sparingly because it makes component reuse more difficult.' In other words, you will not be able to reuse your components 'out of context'.

That is it for this post, thank you for reading through. You can play with the code on  [CodeSandbox](https://codesandbox.io/s/propdrilling-vs-composition-updated-qe8nm?file=/src/App.js:0-878)