Generate React Components using commands from your terminal
Tags: react, javascript, webdev, beginners
Published: 2021-10-07 17:31:36

### Let's first talk about the problem statement. 

Your frontend application **Fatebook** has become huge. You have been following a specific set of patterns to put all the components, pages, shared libraries, etc., in specific directories. Now it is time to hire people but you want to enforce them to follow the same. One way could be a well-documented instruction that they will be given on day 1 and they will be asked to adhere to it.

Another better way would be to create **generators** which would automatically create new components at specified directories.

### Solution
In this blog, we will see the basic use of plopfile generators to create Skeletal React components based on their type from the terminal.


#### Install [plop.js](https://plopjs.com/) as dev dependency of your React project:
```bash
$ npm install --save-dev plop
```
- *Plop.js* uses `plopfile` to perform actions. 
- `add`, `modify`, and `append` are a few of the most commonly used actions.
- We can use the `add` action to create components based on a template. For templating, `plop.js` uses handlebar `template` or `templateFile`.

#### Create a generator that creates a component under the `src/shared_components` directory.
- a generator consists of `prompts` & `actions`.
- *prompts* are used to gather user data. It mainly consists of three properties `type`, `name`, and `message`. Internally `plopjs` uses [https://github.com/SBoudrias/Inquirer.js/#question](Inquirer.js) for executing `prompts`.
- *actions* are used to perform actions of a specific `type` based on the template provided to it.

```js
// generators/shared_component/Component.jsx.hbs
import React from "react";

const {{properCase name}} = (props) => { 
  return <div>{{properCase name}}</div>; 
};

export default {{properCase name}};



// generators/shared_component/index.js
module.exports = {
  description: 'Create a shared component',
  prompts: [
    {
      type: 'input',
      name: 'name',
      message: 'component name(required):',
    },
  ],
  actions: [
    {
      type: 'add',
      path: 'src/components/shared/{{properCase name}}.jsx',
      templateFile: 'generators/shared_component/Component.jsx.hbs',
    },
    {
      type: 'append',
      path: 'src/components/shared/index.js',
      template:
        "export { default as {{properCase name}} } from './{{properCase name}}.jsx';",
    },
  ],
};
```
We have created a `generators` directory at the root of the React project. Inside that, we have two files, one is the template file written with [handlebars](https://handlebarsjs.com/) and another file is the generator itself that contains actions and prompts.

Now we can create a `plopfile.js` at the root level and import the generator created above to use them.
```js
// plopfile.js
const sharedComponentGenerator = require('./generators/shared_component/index');

module.exports = function (plop) {
  plop.setGenerator('shared component', sharedComponentGenerator);
};
```
Now, let's add a script in `package.json` to run the plops.
```js
"scripts": {
  ...
  "generate": "plop"
  },
```

That's it. We can go to our terminal and run `npm run generate` and it will show the prompt to create the shared components.


![Screenshot 2021-09-28 at 6.07.19 PM.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1632832659679/DQfS2PRXZ.png)


### Bonus:
I currently use 3 generators, shared_component, component, and page. Below is the code for it:
```js
// generators/component/Component.jsx.hbs
import React from "react";

const {{properCase name}} = (props) => { 
  return <div>{{properCase name}}</div>; 
};

export default {{properCase name}};


// generators/component/index.js
module.exports = {
  description: 'Create a component',
  prompts: [
    {
      type: 'input',
      name: 'name',
      message: 'component name(required):',
    },
    {
      type: 'input',
      name: 'folder',
      message: 'which folder in /src/components (default is /src/components):',
    },
  ],
  actions: [
    {
      type: 'add',
      path: 'src/components/{{folder}}/{{properCase name}}.jsx',
      templateFile: 'generators/component/Component.jsx.hbs',
    },
  ],
};

// generators/page/Page.jsx.hbs
import React from "react";

const {{properCase name}} = (props) => { 
  return <div>{{properCase name}}</div>; 
};

export default {{properCase name}};

// generators/page/index.js
module.exports = {
  description: 'Create a page',
  prompts: [
    {
      type: 'input',
      name: 'name',
      message: 'page name(required):',
    },
  ],
  actions: [
    {
      type: 'add',
      path: 'src/pages/{{properCase name}}.jsx',
      templateFile: 'generators/page/Page.jsx.hbs',
    },
  ],
};

// plopfile.js
const componentGenerator = require('./generators/component/index');
const sharedComponentGenerator = require('./generators/shared_component/index');
const pageGenerator = require('./generators/page/index');

module.exports = function (plop) {
  plop.setGenerator('component', componentGenerator);
  plop.setGenerator('shared component', sharedComponentGenerator);
  plop.setGenerator('page', pageGenerator);
};
```

Now, when I run `npm run generate`, I get the following:

![Screenshot 2021-09-28 at 6.13.08 PM.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1632832999509/2WEtobzXqb.png)

Thanks for reading till the end. I hope people go through `plop.js` and create stunning automations and share them with the community.