Automate components creation in React project
Tags: react, webdev, javascript, 100daysofcode
Published: 2021-04-26 12:34:22

We write code and create files every day. If you're developing some frontend project most likely you're creating components which start with almost the same folder and file structures. Creating this over and over again is a boring job and one that most of us probably would love to improve.

I was facing that in a React project I'm currently working on and I wanted to automate these initial files every time I wanted to create a component. For that, there is a Javascript called **Plop**.

# What is Plop.js?

As in its [website](https://plopjs.com/), **Plop** is a little tool that saves you time and helps your team build new files with consistency. It makes our life easier when creating files because we just need to setup, create some generators and templates and from that every new files created will follow the same structure.

# How to use it?

#### 1. Installation

```
npm install --save-dev plop
yarn add -D plop
```

#### 2. Create a Plop file

A Plop file is where we create generators for the library to execute when we run `plop` command in terminal.

It is a file where we basically export a function which receives the `plop` object. This object exposes the Plop API which then we can create a generator with the `setGenerator(name, config)` function.

A `generator` is where we define the `prompts`, questions to be asked to the user, and the `actions`, to be performed by Plop for adding, modifying or appending files.

An example taken from the docs for a basic plop file in Javascript:

```javascript
// plopfile.js
module.exports = function (plop) {
	// controller generator
	plop.setGenerator('controller', {
		description: 'application controller logic',
		prompts: [{
			type: 'input',
			name: 'name',
			message: 'controller name please'
		}],
		actions: [{
			type: 'add',
			path: 'src/{{name}}.js',
			templateFile: 'plop-templates/controller.hbs'
		}]
	});
};
```

This generator called _controller_ will ask us for the controller name and will perform a creation of file in the specified path with a dynamic file name and this new file will be structured the same way as _controller.hbs_ file.

#### 3. Create a template file with Handlebars

Handlebars is a templating language, it uses a (wait for it) template with an input object to generate HTML or other text formats. It looks like normal text with some Handlebars expressions. We won't cover more than this, this is the basic stuff to get going here, but you can dive deep in the [docs](https://handlebarsjs.com/guide/).

With this template defined the generator will do its actions and create the files for us. Let's see an example in action.

# Real usage example

I hope the steps above were enough to understand the basic follow. In this section we'll see a real example, the way I used Plop for my current project.

### 1. Creating a Plopfile

For my current project I'm using Atomic Design to structure my components as a way to improve its consistency and reusability.

For each component I create I need to define which folder it is going to be added to, besides its name. These are the `prompts` my `generator` has.

Furthermore, I usually create a 3 files for each component: `index.tsx` for the component itself, `stories.tsx` for the Storybook stories and `test.tsx` for the tests. In this example, to simplify, I'm creating only the first two. So, these are my `actions` for the `generator`.

```javascript
import {NodePlopAPI} from 'plop';

export default function (plop: NodePlopAPI) {
    // controller generator
    plop.setGenerator('component', {
        description: 'Atomic Design component creation logic',
        prompts: [
          {
            type: 'input',
            name: 'name',
            message: 'Component name please',
          },
          {
            type: 'input',
            name: 'level',
            message: 'Atomic Design level of the component please',
          },
        ],
        actions: [
          {
            type: 'add',
            path: '../src/components/{{level}}/{{pascalCase name}}/index.tsx',
            templateFile: 'templates/index.tsx.hbs',
          },
          {
            type: 'add',
            path: '../src/components/{{level}}/{{pascalCase name}}/stories.tsx',
            templateFile: 'templates/stories.tsx.hbs',
          }
        ],
      })
}
```

Bear in mind that the export is a little different from the previous I showed since I'm using Typescript for my project.

So, basically this generator prompts questions for me and according to my answers it creates two files in a dynamically created folder based on the templates.

### 2. Creating the templates

For the templates I created two Handlebars files, one for `stories.tsx` and other for `index.tsx`.

#### 1. `index.tsx`
```typescript
import { Box } from '@chakra-ui/react'

export type {{pascalCase name}}Props = {

}

const {{pascalCase name}} = ({ }: {{pascalCase name}}Props) => (
  <Box>
    {{pascalCase name}}
  </Box>
)

export default {{pascalCase name}}
```

#### 2. `stories.tsx`
```typescript
import {{pascalCase name}}, { {{pascalCase name}}Props } from '.'
import { Story, Meta } from '@storybook/react'

export default {
  title: '{{pascalCase name}}',
  component: {{pascalCase name}},
} as Meta

const Template: Story<{{pascalCase name}}Props> = (args) => <{{pascalCase name}} {...args} />

export const Default = Template.bind({})
Default.args = {

}
```

In each template file, the `{{pascalCase name}}` will be replaced by the name, as a pascal case string, I provided when running `plop` command.

### 3. Run the plop command in a package.json script

To make it easier for me, I created a script called _generate_ to run the `plop` command, the `--plopfile` flag is used to direct the path to my plopfile with the `generator`.

```javascript
// package.json
// ...
  "scripts": {
    //...
    "generate": "yarn plop --plopfile ./plop/plopfile.ts"
  },
// ...
```

When runing `yarn generate`, Plop will ask me the questions I defined and create the files accordingly as seen below:

![Plop execution](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/80erons0svp6fuwfon6b.JPG)

Generated `index.tsx`:

```typescript
import { Box } from '@chakra-ui/react'

export type UserHeaderProps = {

}

const UserHeader = ({ }: UserHeaderProps) => (
  <Box>
    UserHeader
  </Box>
)

export default UserHeader
```

# Conclusion

That's it! You just need to set up Plop and follow the steps to create its generator in the plop file, the templates files and the script to run it. After that, from a simple script call, Plop will do everything for you to make it smoother when creating new components for you application.

Plop can do much more than this and I encourage you to check its docs. For now, this has already made my life easier and I hope it can also help you.

If it was somehow useful, leave it a ❤️ or if you have more to add drop a comment. Also, I'd love if we connect on [Twitter](https://twitter.com/c_rafael22) as well :)