Implementing a decorator design pattern within React.
Tags: react, typescript, javascript, designpatterns
Published: 2023-11-01 22:02:57

One of the many challenges when trying to understand design patterns is making sense of when or where they could be useful. 

Most design pattern examples are written in classes. Now, this isn't _that hard_ to understand if you're programming in a [OOP](https://en.wikipedia.org/wiki/Object-oriented_programming) based programming language like C++, Java, etc. 

But what if were writing Javascript ? More specifically, what if your writing React components ?

Although React has been following a class-based component architecture, it's slowly becoming a thing in the past ever since the release of React 16.8, when functional components became the new way to write components.

So now, we mostly follow a functional programming approach for writing components. 

So how could we implement a design pattern in React ? more specifically how can we implement a _Decorator Design Pattern_ ? 

Lets see how we could achieve this. 

## Problem statement.

Suppose we have a confirm password functionality for a register page. 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v500vkjtfapjbylx3e9r.png)

**Register Page**

```javascript

// this useEffect compares the values of password and confirm password. 

useEffect(() => {
    dispatch(SET_REGISTER_CONFIRM_PASSWORD());
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [formState.password, formState.confirmRegisterPassword]);

// _The rest of the code below is irrelevant for this example.

  const hasError = (field: keyof ErrorState) => (errorState?.[field]?.error ? true : false);
  const updatedChangePasswordMap = renderConfirmPassword
    ? registerFieldMap.concat(renderConfirmRegisterPasswordField)
    : registerFieldMap;

  return (
    <Col lg={12}>
      <Typography className='text-primary font-primary font-bold mb-3' variant='h2'>
        Register
      </Typography>
.......

```
But we also have to do the same for first time googleOauth users. 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m26i33wdym6sfr9p1pku.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/feoivi25ttqcmp50xn2y.png)

So the naive / lazy approach would be to duplicate the useEffect like the following..


**GoogleRegister.tsx**

```javascript
// duplicated again 
 useEffect(() => {
    dispatch(SET_REGISTER_CONFIRM_PASSWORD());
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [formState.password, formState.confirmRegisterPassword]);

  useEffect(() => {
    hasBeenValidated(requiredFields);
  }, [requiredFields]);

  useEffect(() => {
    if (googleId) {
      dispatch(SET_INITAL_FORM_AUTH_STATE({ googleId: googleId, email: googleEmail }));
    }
    checkGoogleAuthenticated();
  }, []);

  const updatedChangePasswordMap =
    formState.password.length >= 6 ? registerFieldMap.concat(renderConfirmRegisterPasswordField) : registerFieldMap;

  return (
    <Col lg={12}>
      <Typography className='text-primary font-primary font-bold mb-3' variant='h4'>
        Just need some more information.
      </Typography>
...
```

How can we keep the functionality centralized ? Write a hook right ? sure we can do that, but why don't we apply the _decorator design pattern_, so we can just wrap the functionality on components who need to use it.

_note: side note, you should probably keep [this](https://www.developerway.com/posts/why-custom-react-hooks-could-destroy-your-app-performance) in mind, when writing custom hooks. Custom hooks are useful, but just have to be mindful of the performance factors._

Heres how we can do it...


```javascript
import { ComponentType, useEffect } from 'react';
import { SET_REGISTER_CONFIRM_PASSWORD, formSelector } from '../redux/store/formSlice';
import { useDispatch, useSelector } from 'react-redux';

/**
 *
 * @param Component @type { ComponentType}
 * @returns
 *
 * Reusable HOC that confirms password for first time registering users.
 */

export function confirmRegisterPassHoc(Component: ComponentType) {
  // we can be more explicit with the props, but for e.g
  return (props: any) => {
    const dispatch = useDispatch() as any;
    const formState = useSelector(formSelector)?.formState;
    useEffect(() => {
      dispatch(SET_REGISTER_CONFIRM_PASSWORD());
      // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [formState.password, formState.confirmRegisterPassword]);

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

And we can just wrap it around like this.



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r4939cayz6oda5wr4m17.png)



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n9vml3z8s9f9acyk7947.png)


So essentially, a higher order component is a decorator design pattern. 

> Decorator is a structural design pattern that lets you attach new behaviors to objects by placing these objects inside special wrapper objects that contain the behaviors.

> The Decorator lets you structure your business logic into layers, create a decorator for each layer and compose objects with various combinations of this logic at runtime. The client code can treat all these objects in the same way, since they all follow a common interface.


source: https://refactoring.guru/design-patterns/decorator

In our example, we didn't need to change anything on the component itself, but just _attach new behavior_ on them without needing to modify the component in any significant way. 


Hopefully, you found this use case helpful, cheers 🥳.