How to autogenerate files for React component from command line
Tags: react, programming, cli, terminal
Published: 2022-05-12 20:57:11

Hello, my name is Ramil and I work as a frontend developer and write code on React for several years. I once read that one of the characteristics of professional programmers is

> the ability and desire to automate those processes around that can be automated

And this prompted me to implement the idea that I want to share in this article.

As a rule, when writing components in React, we often need to perform the same repeatable actions. On the one hand, this is good, because in this way a single code style is formed, on the other hand, this means performing monotonous and routine work, which we would like to avoid. 

## Awareness of problem
Not so long ago, when working on one of my project, I ran into a situation familiar to everyone. In order to create a next component, I need to make few steps:

1. create a folder for all files of the component, so that all files related to the component are nearby, like `components/[ComponentName]`
1. create a file with code of component itself, like `[ComponentName].tsx`
1. create a file for styles (I usually use [css-modules](https://github.com/css-modules/css-modules)), like `[ComponentName].module.css`
1. create a file for types (I prefer to keep types separate from component code), like `[ComponentName].types.ts`
1. create a file `index.ts` for export all necessary data ([barrel file](https://basarat.gitbook.io/typescript/main-1/barrel)) 
![generated files](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6jdz5yav31vi2i6ukbzc.png)

Above, I described only the operations for creating the necessary files. But some files are related to each other, they are imported into each other and use the name of the component within themselves. 
For example, styles and type files are imported into the main component file, and the name of the interface for describing component props is formed from the name of the component.

So after googling and finding [great article](https://levelup.gitconnected.com/how-to-generate-react-components-from-your-terminal-a27741a5b862) from [Mike Theodorou](https://medium.com/@miketheodorou) I decided to supplement a bit his examples and share it with you.

## Script requirements
So, the main requirements for the script to automatically generate a folder with files for the React component were:

- avoid installing new packages and dependencies
- the script should be simple and easily configurable
- the ability to dynamically set the name for the component

## Beginning of work
#### Main configuration
Let's start from file with constants:
`DEFAULT_COMPONENT_BASE_PATH` -  this is the path to the folder where components will be created by default, if no other path was specified
`FILES_DATA` - an array of objects, in fact our main config, where we indicate which files we need and which template to use for this. In this case we want to create 4 files.
{% gist https://gist.github.com/qramilq/b4357b5f278f07b633ba0ecade910db0 file=constants.js%}

##### Templates
Since we've touched on the topic of templates, let's see what a template file looks like. There are no complications here, we just export functions that substitute variables using template strings
{% gist https://gist.github.com/qramilq/b4357b5f278f07b633ba0ecade910db0 file=templates.js%}

##### Working with the command line
Further, in order for our script to request information from the user, we can use the built-in `Node.js` module called [readline](https://nodejsdev.ru/api/readline/). 
To use it, in our case, we need 3 steps:
1. create an instance using a method `createInterface`
1. read data from the command line using instance method `question`
1. close "connection" to command line using instance method `close()`

Following the [single responsibility principle](https://en.wikipedia.org/wiki/Single-responsibility_principle), I decided to combine all the work with the `readline` module into a `Readline` wrapper class, where I added public methods to call the `question` and `close` methods.
{% gist https://gist.github.com/qramilq/b4357b5f278f07b633ba0ecade910db0 file=readline.js%}

##### Helper functions
In order to make the code of our main script as clean as possible, I decided to decompose the code and move some functions outside of it.

Here we got:
- functions for get information from the command line about the name and path of the component, and processing the entered values

From the function for getting the name of the component, I return the name of the component with a capital letter, because React component names always starts with a capital letter and I'm too lazy and don't want to hold down `Shift` every time I type component name in command line :sweat_smile: so I did this modification for myself. 
From the function for getting the path for the folder with the component, I return the default path if nothing was entered on the command line.

- function to create files based on our config based on `FILES_DATA`
{% gist https://gist.github.com/qramilq/b4357b5f278f07b633ba0ecade910db0 file=helpers.js%}

##### Script entry point
And finally, we need an entry point. This is a main script file in which we will combine all our logic and the same script that we will run to autogenerate files for React component from command line. 
I didn't add a large number of checks and other things. Here is only a basic check to see if such a component already exists, and if not, then create a directory and generate component files.
{% gist https://gist.github.com/qramilq/b4357b5f278f07b633ba0ecade910db0 file=generate-component.js%}

##### Run the script
That's all, now it remains to run the script. My folder with this script is in the root of the project with the following structure:
![Generate script folder structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5ubjksa49az6hbzr4mm2.png)

To start, I only need to run the `generate-component.js` script file using `Node.js`. In my case it will be like this: ```sh
node ./.scripts/generate-component/generate-component.js 
```

If desired, the script call can be placed in a `package.json` file in `scripts` section:
```json
{
  "scripts": {
    "generate-component": "node ./.scripts/generate-component/generate-component.js",
  }
}
```

Final gist with all files you can find [here](https://gist.github.com/qramilq/b4357b5f278f07b633ba0ecade910db0)

## Conclusion
It was one of the options for solving this problem. Of course, there are already ready-made npm packages for this, but I wanted to try to write something of my own and simple, and I think that this was quite successful. Finally, I would like to note the idea with which this post began: 

> if possible, try to automate routine work. This will either save you time in the future, or at least give you a good programming experience.