Are you creating React components like this

Are you creating React components like this

Create React components with just one command

Let's first talk about the problem statement.

Your frontend application Hashlink 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 as dev dependency of your React project:

$ 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 for executing prompts.
  • actions are used to perform actions of a specific type based on the template provided to it.
// 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 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.

// 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.

"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

Bonus:

I currently use 3 generators, shared_component, component, and page. Below is the code for it:

// 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

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

Did you find this article valuable?

Support Akhil Gautam by becoming a sponsor. Any amount is appreciated!