Creating Resilient Components with useMemo
Tags: react, javascript, webdev, tutorial
Published: 2021-01-04 23:54:50

---
tags:
- react
- javascript
- webdev
- tutorial
published: true
title: Creating Resilient Components with useMemo
cover_image: https://miro.medium.com/max/1200/0*u5vgVgQIkItnTN_O.jpg
---

Today we will looking at a principle of creating resilient components in React and creating a useful custom hook with the **useMemo** hook. Sometimes when creating a component, we can assume that it will only be used once. 

However, that assumption may lead into problems sharing props when reusing a simple component. In our example here today, we will look at creating a resilient form component.

> Sometimes we assume a certain component is only ever displayed once. Such as a navigation bar. This might be true for some time. However, this assumption often causes design problems that only surface much later. - [Dan Abramov](https://overreacted.io/writing-resilient-components/)

You can check out the completed code to follow along [here](https://github.com/joefstack/usememo-unique-ids) and the demo in action [here](https://usememo-unique-ids.netlify.app/).

## The Setup

We will start by bootstrapping a project with **create-react-app** and installing the **react-bootstrap** and **shortid** packages. I will be using the **shortid** package in this demo to create our randomly generated unique IDs, but you can use any method you like to create a random ID string.

```
npx create-react-app usememo-resilient-components;
cd usememo-resilient-components;
npm i react-boostrap shortid;
npm start;
```

Don't forget to add the CDN link for the bootstrap css files as **react-bootstrap** does not include them. You can follow the **react-bootstrap** docs [here](https://react-bootstrap.github.io/getting-started/introduction).

```
// index.html

...
<link
  rel="stylesheet"
  href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"
  integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk"
  crossorigin="anonymous"
/>
...

```


## Creating the form handler

Let's start by going into our App.js, clearing out the boilerplate, and creating our form handler. We will set an empty object using the **useState** hook to store our parameters. To maximize modularity, in our form handler function we will pass a callback to setParams that target the name and value attributes of as many form elements as necessary. 

Also, let's import some bootstrap elements from our **react-bootstrap** package and set the container and column to display for now. Your **App.js** should look like this:

```
// App.js

import { useState } from "react";
import { Container, Col } from "react-bootstrap";

function App() {
  const [params, setParams] = useState({});
  const handleChange = (e) => {
    const param = e.target.name;
    const value = e.target.value;
    setParams((prevParams) => {
      return { ...prevParams, [param]: value };
    });
  };

  return (
    <Container>
      <Col lg="5">
        <h1>Generate Unique IDs Demo</h1>
      </Col>
    </Container>
  );
}

export default App;

```

## Creating our form and displaying the input

Next, create we will create our form component. For this demo, I have imported a basic two element form from **react-bootstrap**, but feel free to add as many form elements as you want. Our component will be passed our handler function as a prop from **App.js** to handle our form onChange attribute. 

```
// InputForm.js

import { Form } from "react-bootstrap";

export default function InputForm({ handleChange }) {
  return (
    <Form className="mb-2">
      <Form.Group>
        <Form.Label>Email</Form.Label>
        <Form.Control
          type="email"
          placeholder="Enter email"
          name="email"
          onChange={handleChange}
        />
      </Form.Group>
      <Form.Group>
        <Form.Label>Name</Form.Label>
        <Form.Control
          type="text"
          placeholder="Enter Name"
          name="name
          onChange={handleChange}
        />
      </Form.Group>
    </Form>
  );
}

```

To see what our returned parameters are in state, we could simply log them to our console, but I have created a component to display our parameters on our page for this demo. My component will map through all of the parameters passed from our form handler in **App.js** and display them in a Jumbotron element. 

```
// DisplayInput.js

...

import React from "react";
import { Jumbotron } from "react-bootstrap";

export default function DisplayInput({ params }) {
  const paramKeys = Object.keys(params);
  return (
    <Jumbotron>
      {paramKeys.map((key) => {
        return <p key={key}>{key + ": " + params[key]}</p>;
      })}
    </Jumbotron>
  );
}

...

```

Now we can import both elements into our **App.js** and pass the handler to our form component and pass our parameters in state to our display component.

```
// App.js
...

import DisplayInput from "./Components/DisplayInput";
import InputForm from "./Components/InputForm";

...

return (
  <Container>
    <Col lg="5">
      <h1>Generate Unique IDs Demo</h1>
      <InputForm handleChange={handleChange} />
      <DisplayInput params={params} />
    </Col>
  </Container>
);

...

```

When you run **npm start**, you should be able to see our the name and value of our inputs displayed in our Jumbotron.

![Single Component Input Display](https://dev-to-uploads.s3.amazonaws.com/i/2a7attjbcu5fvij73m8t.png)


## The Problem

This becomes problematic when you want to reuse the same form component again with the same handler. In our **App.js**, let's render our form component again. 

```
// App.js

...

return (
  <Container>
    <Col lg="5">
      <h1>Generate Unique IDs Demo</h1>
      <InputForm handleChange={handleChange} />
      <InputForm handleChange={handleChange} />
      <DisplayInput params={params} />
    </Col>
  </Container>
);
...

```

You can see in the figure below that our parameters prop will not distinguish between our inputs from both form components:

![Multiple Component Display Problem](https://dev-to-uploads.s3.amazonaws.com/i/e504e0upjx9uh144237p.png)

We could solve this issue with writing a separate form handler function. But let's say that you want to use the form component multiple more times. You would have to create a separate function to pass to each form. 

## Creating a custom useMemo hook 

**useMemo** is a hook included in react that returns a memoized value. This means that it will only fire if one of its dependencies changes. This means that it will not recalculate methods that are computationally expensive upon each re-render, if its passed values do not change. You can read more about it in the react hooks docs [here](https://reactjs.org/docs/hooks-reference.html#usememo). 

Under a new directory, we will create our custom **useUniqueId.js** hook file. We will create a variable and pass **useMemo** our id generator function and an empty array. Like with the **useEffect** hook, the empty array will tell **useMemo** to only fire once per component render. Lastly, our hook will return generated unique id with our element name suffix.

```
// useUniqueId.js

...

import { useMemo } from "react";
const shortid = require("shortid");

const useUniqueId = () => {
  const uniqueId = useMemo(() => shortid.generate(), []);
  return (elementNameSuffix) => `${uniqueId}_${elementNameSuffix}`;
};

export default useUniqueId;

...

```

Now we can import our custom **useUniqueId** hook into our form component and pass it to our name attributes in the form elements. 

```
// useUniqueId.js

...

import { Form } from "react-bootstrap";
import useUniqueId from "../helpers/useUniqueId";

export default function InputForm({ handleChange }) {
  const generateId = useUniqueId();
  return (
    <Form className="mb-2">
      <Form.Group>
        <Form.Label>Email</Form.Label>
        <Form.Control
          type="email"
          placeholder="Enter email"
          name={generateId("email")}
          onChange={handleChange}
        />
      </Form.Group>
      <Form.Group>
        <Form.Label>Name</Form.Label>
        <Form.Control
          type="text"
          placeholder="Enter Name"
          name={generateId("name")}
          onChange={handleChange}
        />
      </Form.Group>
    </Form>
  );
}

...

```

Finally, let's run our app again and see the result. 

![Multiple Component Unique Parameters](https://dev-to-uploads.s3.amazonaws.com/i/j0m5rqwoa838t626vwvq.png)

As you can see, now our parameters can be distinguished uniquely from each other, no matter how many times we render our form component!

## Congratulations!!

We now our form components can be rendered multiple times without having to worry about our parameters being lost and overwritten. Our custom hook can also be used on any attribute in any component that you want to re-use.

You can check out the completed code [here](https://github.com/joefstack/usememo-unique-ids) and the demo in action [here](https://usememo-unique-ids.netlify.app/).