DEV Community

Cover image for Generate React CLI
arminbro
arminbro

Posted on • Edited on

Generate React CLI

I enjoy working on React projects, but one thing that gets in the way of staying productive is having to write or copy boilerplate code repetitively when creating new components.

Create React App and Gatsby do a great job of initializing new projects, setting up the development environment, and optimizing the app for production use. Still, they don't have a way to generate new components similar to what Angular CLI offers, and that's because they both try to stay as non-opinionated as possible and allow the developer to make those decisions. One example would be grouping by features vs. grouping by file type when creating components.

Generate React CLI, on the other hand, currently focuses on one thing, and that's generating new components by running a simple command. It also doesn't care if you run it in an existing CRA, Gatsby, or a custom React project you built on your own.

It does, however, have an opinion on how component files are structured. It follows grouping by feature, and that's because we believe when you look at a component, you should see all of its corresponding files (i.e., stylesheet, test, and component) under one folder with the component name. We feel this approach provides a better developer experience.

A great Medium post on how to structure a React project: "The 100% correct way to structure a React app (or why thereโ€™s no such thing)" by David Gilbertson

How to use Generate React CLI

Before you get started, make sure to have Node >= 10.x and NPM >= 6.x installed on your machine.

You can run it using npx like this:

  npx generate-react-cli component Box
Enter fullscreen mode Exit fullscreen mode

(npx is a package runner tool that comes with npm 5.2+)

Config File

When you run GRC within your project the first time, it will ask you a series of questions to customize the cli for your project needs (this will create a "generate-react-cli.json" config file).

Example of the generate-react-cli.json config file:

{
  "usesTypeScript": false,
  "usesCssModule": true,
  "cssPreprocessor": "scss",
  "testLibrary": "Testing Library",
  "component": {
    "default": {
      "path": "src/components",
      "withLazy": false,
      "withStory": false,
      "withStyle": true,
      "withTest": true
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Generate Components

  npx generate-react-cli component Box
Enter fullscreen mode Exit fullscreen mode

This command will create a folder with your component name within your default (e.g. src/components) directory, and its corresponding files.

Example of the component files structure:

|-- /src
    |-- /components
        |-- /Box
            |-- Box.js
            |-- Box.css
            |-- Box.test.js
Enter fullscreen mode Exit fullscreen mode

Options

You can also override some of the GRC component config rules using one-off commands. So for example, let's say you have set withTest to be true in the component.default property. You can override it like this:

  npx generate-react-cli component Box --withTest=false
Enter fullscreen mode Exit fullscreen mode

Or vice versa, if you have set withTest to be false you can do this:

  npx generate-react-cli component Box --withTest=true
Enter fullscreen mode Exit fullscreen mode

Otherwise, if you don't pass any options, it will just use the default values that you have set in the GRC config file under component.default.

Options Description Value Type Default Value
--path Value of the path where you want the component to be generated in (e.g. src/components). String component.default.path
--type You can pass a custom component type that you have configured in the GRC config file that has its own set of component config rules. Read more about custom component types. String component.default
--withLazy Creates a corresponding lazy file (a file that lazy-loads your component out of the box and enables code splitting) with this component. Boolean component.default.withLazy
--withStory Creates a corresponding (storybook) story file with this component. Boolean component.default.withStory
--withStyle Creates a corresponding stylesheet file with this component. Boolean component.default.withStyle
--withTest Creates a corresponding test file with this component. Boolean component.default.withTest

Custom component types:

By default, GRC will use the component.default configuration rules when running the component command out of the box.

What if you wanted to generate other types of components that have their own set of config rules (e.g., page or layout)?

You can do so by extending the generate-react-cli.json config file like this.

{
  "usesTypeScript": false,
  "usesCssModule": true,
  "cssPreprocessor": "scss",
  "testLibrary": "Testing Library",
  "component": {
    "default": {
      "path": "src/components",
      "withLazy": false,
      "withStory": false,
      "withStyle": true,
      "withTest": true
    },
    "page": {
      "path": "src/pages",
      "withLazy": true,
      "withStory": false,
      "withStyle": true,
      "withTest": true
    },
    "layout": {
      "path": "src/layout",
      "withLazy": false,
      "withStory": false,
      "withStyle": false,
      "withTest": true
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Now you can generate a component with your custom component types like this:

  npx generate-react-cli component HomePage --type=page
Enter fullscreen mode Exit fullscreen mode
  npx generate-react-cli component BoxLayout --type=layout
Enter fullscreen mode Exit fullscreen mode

You can also pass the same options to your custom component types as you would for the default component type.

Custom component templates

You can also create your own custom templates that GRC can use instead of the built-in templates that come with it. We hope this will provide more flexibility for your components that you want to generate.

There is an optional customTemplates object that you can pass to the component.default or any of your custom component types within your generate-react-cli.json config file.

Example of the customTemplates object:

"customTemplates": {
  "component": "templates/TemplateName.js",
  "lazy":  "templates/TemplateName.lazy.js",
  "story":  "templates/TemplateName.story.js",
  "style": "templates/TemplateName.style.scss",
  "test":  "templates/TemplateName.test.js"
},
Enter fullscreen mode Exit fullscreen mode

The keys represent the type of file, and the values are the paths that point to where your custom template lives in your project/system. Please note the TemplateName keyword in the template filename. GRC will use this keyword and replace it with your component name as the filename.

Example of using the customTemplates object within your generate-react-cli.json config file:

{
  "usesTypeScript": false,
  "usesCssModule": true,
  "cssPreprocessor": "scss",
  "testLibrary": "Testing Library",
  "component": {
    "default": {
      "customTemplates": {
        "component": "templates/component/TemplateName.js",
        "style": "templates/component/TemplateName.style.scss",
        "test": "templates/component/TemplateName.test.js"
      },
      "path": "src/components",
      "withStyle": true,
      "withTest": true,
      "withStory": true,
      "withLazy": false
    },
    "page": {
      "customTemplates": {
        "test": "templates/page/TemplateName.test.js"
      },
      "path": "src/pages",
      "withLazy": true,
      "withStory": false,
      "withStyle": true,
      "withTest": true
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Notice in the page.customTemplates that we only specified the test custom template type. That's because all the custom template types are optional. If you don't set the other types, GRC will default to using the built-in templates it comes with.

Example of a custom component template file:

// templates/component/TemplateName.js

import React from 'react';
import styles from './TemplateName.module.css';

const TemplateName = () => (
  <div className={styles.TemplateName} data-testid="TemplateName">
    <h1>TemplateName component</h1>
  </div>
);

export default TemplateName;
Enter fullscreen mode Exit fullscreen mode

Important - Make sure to use the TemplateName keyword in your templates as well. GRC will also use this keyword to replace it with your component name.

Example of a custom test template file:

// templates/component/TemplateName.test.js

import React from 'react';
import ReactDOM from 'react-dom';
import TemplateName from './TemplateName';

it('It should mount', () => {
  const div = document.createElement('div');
  ReactDOM.render(<TemplateName />, div);
  ReactDOM.unmountComponentAtNode(div);
});
Enter fullscreen mode Exit fullscreen mode

Custom component files

GRC comes with corresponding built-in files for a given component if you need them (i.e., withStyle, withTest, withStory, and withLazy).

What if you wanted to add custom files of your own?

For example, let's say you wanted to add an index.js file for each component, so you don't have to add the additional component name with each import (i.e., import Box from './components/Box' instead of import Box from './components/Box/Box').

Or maybe you need an additional style file for your component stories.

You can do so by editing your generate-react-cli.json config file like so.

{
  "usesTypeScript": false,
  "usesCssModule": false,
  "cssPreprocessor": "css",
  "testLibrary": "Testing Library",
  "component": {
    "default": {
      "path": "src/components",
      "withStyle": true,
      "withTest": true,
      "withStory": true,
      "withLazy": false,
      "withIndex": true,
      "withStoryStyle": true,
      "customTemplates": {
        "index": "templates/default/index.js",
        "storyStyle": "templates/default/TemplateName.stories.css"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode
// templates/default/index.js

export { default } from './TemplateName';
Enter fullscreen mode Exit fullscreen mode
/* templates/default/TemplateName.stories.css */

.TemplateName {}
Enter fullscreen mode Exit fullscreen mode

In this case, we added a withIndex & withStoryStyle to the component.default. Note: You can add custom files to any of your custom component types.

You should also see that we added index and storyStyle to our customTemplates object. That's because custom files require custom templates. Otherwise, you will get an error when you generate a component.

Also, we used the TemplateName keyword for the storyStyle custom file. GRC will generate this corresponding file and replace TemplateName with the component name.

That's it. I hope GRC helps you stay productive in your React projects.

โœŒ,
Armin

Top comments (2)

Collapse
 
anandkashyap profile image
Anand Kashyap • Edited

Thanks man!
I was looking for this. Has all the options I needed except one- it does not allow you to customise the folder name or if skip the folder creation. Any plans for this?
Anyways I created a custom vscode task to work with this package and new component creation is lightning fast now.

Collapse
 
anshles profile image
Ansh Saini

EXACTLY what I was looking for. Thank you so much for creating this beautiful package.