Reducing manual work in React with Hygen
Tags: react, hygen, webdev, tutorial
Published: 2024-02-26 17:40:43

## Introduction

When creating new components and modules in a React app, a project pattern is usually followed, of folder structure and file types. Based on the creation of a new component, one can proceed in the following ways: by duplicating folders and files from another component in the app, renaming file names, updating imports, and replacing code to match the definitions of the new component, or by creating folders and files manually. But how could the efficiency of this process of creating a new component be improved to be less manual?

## Hygen

Hygen is a automatic code generation library, that based on templates definitions allows the generation of files and specifies the location in the application where these files will be created.

## Setup

To add Hygen to the application, it's necessary to run the following command:

`yarn add --dev hygen`

To start Hygen in the project:

`npx hygen init self`

It will generate a `_templates` folder where two folders will be created with some initial files, that will allow Hygen use. In `_templates` folder, we will define the templates for files generation.

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

Next, it will be necessary to create a code generator from the following command, where instead of `generator_name`, it is defined the name that represents it (for example, `component` can be put for a component generator):

`npx hygen generator new generator_name`

This command will generate a folder structure `_templates/generator_name/new`, with an initial example template. Inside `generator_name/new`, all the templates that will be used, when running the generator in the terminal, will be defined. The initial example template (hello.ejs.t) comes with the following code:

~~~
---
to: app/hello.js
---
const hello = ```
Hello!
This is your first hygen template.

Learn what it can do here:

https://github.com/jondot/hygen
```

console.log(hello)

~~~

Where `to:` defines the location where the new file will be created, and below it is the code that will be generated. All template files follow the pattern `template_name.ejs.t`.

To run the generator and create new files from the templates defined inside it, I suggest creating a script in `package.json` for execute `hygen generator_name new`. Here's an example starting from a generator with `generator_name` equal to `component`:

```
"scripts": {
  (...),
  "create-component": "hygen component new"
},
```

For executing the generator:

`yarn create-component`

After executing this command, all templates inside `component/new` will generate new files.

In addition to creating new files, Hygen allows code injection into existing files. For this purpose, `to:` have to be set to the path of an existing file inside the app. Inside the template, needs to define `inject: true`, and to specify the injection point, one way is to define the line to be included by adding `at_line:`, following the structure below:

```
---
inject: true
to: existing_file_path
at_line: 0
---
```

It's also possible to pass a dynamic value inside the templates by using `<%=name%>`, both in the definition of the code to be generated and in the definition of the file location. Below is an example of usage in the definition of the file location:

```
---
to: src/components/<%=name%>.js
---
```

Using the example of a generator named `component`, when executing the command `yarn create-component Input`, the `<%=name%>` in the template above will be replaced by `Input`, and the file from this template will be generated in `src/components/Input.js`.

## Execution example

Now I will present an example of executing Hygen to generate a new component. The idea is to demonstrate the process of creating files and injecting code into an existing file. Let's start with an app that has the following structure:

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

In `src/components/Tag/Tag.js`, the component is defined:

```
import React from "react";

const Tag = ({(...)}) => (
  <div>
    (...)
  </div>
);

export default Tag;
```

In `src/components/Tag/Tag.test.js`, the tests:

```
import React from "react";
import "@testing-library/jest-dom";
import { render, screen } from "@testing-library/react";

import Tag from "./Tag";

describe("<Tag />", () => {
  (...)
});
```

In `src/components/Tag/index.js`, the export inside the component folder:

```
export { default } from "./Tag";
```

In `src/components/index.js`, the export inside the `components` folder:

```
export { default as Tag } from "./Tag";
```

The first step is to create the code generator, that, as it is for component creation, I'll call component. Executing in the terminal:

`npx hygen generator new component`

This way, the folder structure `_templates/component/new` will be created with an example file.

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

As the file `hello.ejs.t` won't be used, it will be removed, and inside the `new` folder, the templates will be added. For the component creation, the template `component.ejs.t` will be created:

```
---
to: src/components/<%=name%>/<%=name%>.js
---
import React from "react";

const <%=name%> = ({}) => (

);

export default <%=name%>;

```

For the tests, the template `test.ejs.t`:

```
---
to: src/components/<%=name%>/<%=name%>.test.js
---
import React from "react";
import "@testing-library/jest-dom";
import { render, screen } from "@testing-library/react";

import <%=name%> from "./<%=name%>";

describe("<<%=name%> />", () => {

});

```

For the export inside the component folder, the template `index.ejs.t`:

```
---
to: src/components/<%=name%>/index.js
---
export { default } from "./<%=name%>";

```

For the export inside the components folder, since the file already exists and has the export of the Tag component inside it, the code injection will be done using the template `componentsIndex.ejs.t`:

```
---
inject: true
to: src/components/index.js
at_line: 0
---
export { default as <%=name%> } from "./<%=name%>";
```

The `<%=name%>` will be the name of the component to be created, which will be defined when running the command to use the generator `component`. The templates will be defined as follows:

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

To execute the component generator, it will be added to `package.json`:

```
"scripts": {
  "create-component": "hygen component new"
},
```

In this example, a button component called `Button` will be created. Therefore, when running the generator command, it will be necessary to add `Button` at the end, to all templates replace `<%=name%>` with `Button`:

`yarn create-component Button`

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

Showing in the terminal the three generated files and the existing file that had code added to it.

The folder structure, files, and code will be as defined in the templates.

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

## Conclusion

Finally, the idea of this article is to demonstrate a way to reduce manual work in React development by automating part of the process. I provided an example related to creating components to illustrate how it works, but I have also encountered the use of Hygen for generating modules, which share the same folder structure, file types, Babel configuration, TypeScript setup, among others, speeding up the process of creating them using the library.