DEV Community

Cover image for Composition vs Context in React
bhupendra
bhupendra

Posted on • Updated on

Composition vs Context in React

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.

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 .

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";
};
Enter fullscreen mode Exit fullscreen mode

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

First thing that comes to mind in solving Props Drilling problem is to use the Context API.

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

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";
};
Enter fullscreen mode Exit fullscreen mode

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

, but before we try to solve props drilling with Composition,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 :

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";
};
Enter fullscreen mode Exit fullscreen mode

💡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 :

Top comments (0)