Composition vs Context in React
Tags: react, javascript, programming
Published: 2021-09-14 17:30:41

In a React App , there are two types of states that needs to be managed :
1. Sever Cache : state that is unique for a page and syncs to DB
2. UI State : state that refreshes on reload of page

When we talk about State Management in React , we refer to the **UI State** . Based upon how many components share the same state  either we can *Lift the State up* ⬆ to the least common parent element Or we can *co-locate*⬇ the state to the component where it's used. This is explained in depth by Kent in his [blog](https://kentcdodds.com/blog/application-state-management-with-react).

The problem arises when we have the state at top and it has to be passed via props to a deeply nested component, although the intermediate components don't require the state value , but they have to receive and forward to any of child component. This behavior is called **Props drilling** .

```java
function App() {
  const [status, setStatus] = React.useState(false);
  return <Header status={status} />;
}

const Header = ({ status }) => {
  return <Account status={status} />;
};

const Account = ({ status }) => {
  return status ? "LogOut" : "LogIn";
};
```
In above code Header Component does not require *status* prop but only forwards it to the Account component which shows Log Out/In option based upon status prop.
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vk88valj1lifuc9xuk1s.png)

First thing that comes to mind in solving Props Drilling problem is to use the [Context API](https://reactjs.org/docs/context.html). 

Let's see how to avoid props forwarding with context API :

```java
const StatusContext = React.createContext();

function App() {
  const [status, setStatus] = React.useState(false);
  return (
    <StatusContext.Provider value={status}>
      <Header />
    </StatusContext.Provider>
  );
}

const Header = () => {
  return <Account />;
};

const Account = () => {
  const status = React.useContext(StatusContext);
  return status ? "LogOut" : "LogIn";
};
```
> If you only want to avoid passing some props through many levels, component composition is often a simpler solution than context. ~ **[React docs](https://reactjs.org/docs/context.html#before-you-use-context)**

 , but before we try to solve props drilling with [Composition](https://reactjs.org/docs/composition-vs-inheritance.html),let's understand what does *composition* mean ~ Composition means building ⚒ or choosing what goes inside a component. So instead of writing ```<Header />``` , we can refer it to as ```<Header>  <Account status={status} /></Header>```
React by default provides a *children* prop to all nested components and it's using this special props it becomes possible to make scalable & reusable components.

Let's see how to apply solve props drilling problem by composition :
```java
function App() {
  const [status, setStatus] = React.useState(false);
  return (
    <Header>
      <Account status={status} />
    </Header>
  );
}

const Header = ({ children }) => {
  return <>{children}</>;
};

const Account = ({ status }) => {
  return status ? "LogOut" : "LogIn";
};
```

💡Context should be used when data is needed for many components at different nesting levels. Using Context makes the component less reusable as the consumer component can't be used outside the provider component hierarchy. 

Complete Example with both approaches : 
{% codesandbox composition-216od %}