React HOC to make components permission driven
Tags: javascript, react, webdev, tutorial
Published: 2022-10-01 14:27:58

## This is a design pattern which I’ve used in most of my React applications to limit the access level of components.

Before diving deep into the solution, let’s first understand what a **High Order Component (HOC)** is ?

**HOC** is an advanced technique in React for reusing component logic. They are a pattern that is based upon the concept of **High Order Functions** in **JavaScript**. In layman terms, a **HOC** is a function that takes a component and returns a new component. It is not a part of React API but simple fact is that it emerges from **React’s compositional nature**.

In this solution, I’m going to use following functionalities to achieve the end result:

- **React**: version ≥ 16.8
- **JavaScript**
- **Global State Management**: To store the user permissions and pass it down through the component tree. I’ll be using **Context-Reducer**, you can use any other library also such as Redux, MobX or Zustand etc.

### Solution:
To start, let us assume that we have an application where we need to limit our application’s component access level based upon particular user’s permission.

- Initially, we have 4 components:

**Component1** : should be accessible if user has `ACCESS_COMPONENT1` permission.

```react
import React from "react";

const Component1 = (props) => {
  return (
    <p>Component only accessible if user has ACCESS_COMPONENT1 permission</p>
  );
};

export default Component1;
```

**Component2** : should be accessible if user has `ACCESS_COMPONENT2` permission.

```react
import React from "react";

const Component2 = (props) => {
  return (
    <p>Component only accessible if user has ACCESS_COMPONENT2 permission</p>
  );
};

export default Component2;
```

**Component3** : should be accessible if user has `ACCESS_COMPONENT3` permission.

```react
import React from "react";

const Component3 = (props) => {
  return (
    <p>Component only accessible if user has ACCESS_COMPONENT3 permission</p>
  );
};

export default Component3;
```

**App** : parent wrapper which imports the above 3 components
```react
import React from "react";
import Component1 from './Component1';
import Component2 from './Component2';
import Component3 from './Component3';

const App = (props) => {
  return (
    <div>
      <Component1 />
      <Component2 />
      <Component3 />
    </div>
  );
};

export default App;
```

- Let us create a component **`UserPermissionProvider`** which will fetch the user permissions from some API, store it and make it available to its children. It will also export **`UserPermissionStore`** context that we can consume in our component tree to access the store.

> Note: I’ll be hardcoding the permissions in this example

```react
import React, { createContext, useState, useEffect } from "react";

export const UserPermissionStore = createContext({ userPermission: {} });

const UserPermissionProvider = (props) => {
  const { children } = props;
  const [userPermission, setUserPermission] = useState({});

  useEffect(() => {
    const permissions = {
      ACCESS_COMPONENT1: "ACCESS_COMPONENT1",
      ACCESS_COMPONENT2: "ACCESS_COMPONENT2",
      ACCESS_COMPONENT3: "ACCESS_COMPONENT3",
    };
    setUserPermission(permissions);
  }, []);

  return (
    <UserPermissionStore.Provider value={{ userPermission }}>
      {children}
    </UserPermissionStore.Provider>
  );
};

export default UserPermissionProvider;
```

- We will now pass our **`App`** component as a child within **`UserPermissionProvider`** component so that our App component tree has access to **`UserPermissionStore`** context.
```react
import React from "react";
import Component1 from "./Component1";
import Component2 from "./Component2";
import Component3 from "./Component3";
import UserPermissionProvider from "./UserPermissionProvider";

const App = (props) => {
  return (
    <UserPermissionProvider>
      <div>
        <Component1 />
        <Component2 />
        <Component3 />
      </div>
    </UserPermissionProvider>
  );
};

export default App;
```

- Now we will create a HOC **`withUserPermission`** that will take a Component and the permission required to access that Component as input. It will return the Component if supplied permission is valid otherwise nothing is returned.
```react
import React, { useContext } from "react";
import { UserPermissionStore } from "./UserPermissionProvider";

const withUserPermission = (Component, requiredPermission) => (props) => {
  const { userPermission } = useContext(UserPermissionStore);

  if (!userPermission[requiredPermission]) return null;

  return <Component {...props} />;
};

export default withUserPermission;
```

- We will create our new enhanced components using **`withUserPermission`** HOC which will be only accessible if the permission needed to access them is available in user permissions.
```react
import React from "react";
import withUserPermission from "./withUserPermission";

const Component1: React.FC = (props) => {
  return (
    <p>Component only accessible if user has ACCESS_COMPONENT1 permission</p>
  );
};

export default withUserPermission(Component1, 'ACCESS_COMPONENT1');
```

> Note: Similarly we will update our **Component2** and **Component3** as well with their respective permissions.

#### I have tried to explain the best method that I know. If you know others, share in the comments for everyone!
#### Thanks For Reading, Follow Me For More