Generate React CLI
Why?
To help speed up productivity in React projects and stop copying, pasting, and renaming files each time you want to create a new component.
A short article goes deeper into why we created GRC if you have the time.
You can also watch an excellent video tutorial on how to use GRC by Eric Murphy.
Table of Contents:
- Config file
- Generate components
- Custom component types
- Custom component templates
- Custom component files
- OpenAi integration (Alpha release)
You can run it using npx like this:
npx generate-react-cli component Box
(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": true,
"usesCssModule": true,
"cssPreprocessor": "scss",
"testLibrary": "Testing Library",
"component": {
"default": {
"path": "src/components",
"withLazy": false,
"withStory": false,
"withStyle": true,
"withTest": true
}
}
}
Generate Components
npx generate-react-cli component Box
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
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
Or vice versa, if you have set withTest to be false
you can do this:
npx generate-react-cli component Box --withTest=true
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 |
--dry-run | Show what will be generated without writing to disk | Boolean | false |
--flat | Generate the files in the mentioned path insted of creating new folder for it | Boolean | false |
--describe | Describe the component you're trying to generate, and OpenAI will do its best to render it following your instructions. | String | null |
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
}
}
}
Now you can generate a component with your custom component types like this:
npx generate-react-cli component HomePage --type=page
npx generate-react-cli component BoxLayout --type=layout
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.
customTemplates
object:
Example of the "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"
},
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 (in whichever format you typed the component name in the command) as the filename.
customTemplates
object within your generate-react-cli.json config file:
Example of using the {
"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
}
}
}
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;
Important - You can also use the following keywords within your custom templates to format the component name in your templates accordingly:
Keyword | Replacement |
---|---|
templatename |
component name in raw case (whichever format the user typed the component name in the command) |
TemplateName |
component name in PascalCase |
templateName |
component name in camelCase |
template-name |
component name in kebab-case |
template_name |
component name in snake_case |
TEMPLATE_NAME |
component name in uppercase SNAKE_CASE |
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);
});
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"
}
}
}
}
// templates/default/index.js
export { default } from './TemplateName';
/* templates/default/TemplateName.stories.css */
.TemplateName {
}
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.
OpenAI integration (Alpha release)
Well, the time has come to incorporate OpenAI with GRC.
I had a chance to experiment with OpenAI's latest GPT-3 natural language model, and I was super impressed by its capabilities. You can read more about OpenAI by visiting their site: https://openai.com/.
If you've been using GRC, you already know about its component generation capabilities using its internal templates or the custom ones you provide.
With the help of OpenAI, we can now generate our components intelligently by describing them using the new --describe
flag, or -d
for short.
The plan for this alpha integration will start simple, but I have a few good ideas coming in the near future (and I'm hoping to hear some of yours) on how we can use OpenAI with GRC to improve the developer experience.
Please remember that this release is still early, and you will run into bugs. So, please report any bugs or issues here.
Okay, let's get started.
- If you don't have one, you must create an OpenAI account: https://openai.com/api/.
- You'll need to obtain a secret API key from OpenAI. You can do so by visiting https://beta.openai.com/account/api-keys.
- Once you have your API key, you'll need to create a
.env.local
file in your react project and store it as a variable asOPENAI_API_KEY
. Please be sure not to share the key or push it to version control, as it is private.
GRC will pass the key to OpenAI to communicate with the API on your behalf. You will see the usage reflected on your OpenAI account here: https://beta.openai.com/account/usage.
GRC uses the DaVinci language model, so you can check out their pricing here: https://openai.com/api/pricing/.
Let's generate our first component using OpenAI:
npx generate-react-cli@alpha c Counter -d "Create a counter component that increments by one when I click on the increment button"
GRC should have created a Counter component that looks something like this
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import './Counter.css';
const Counter = () => {
const [count, setCount] = useState(0);
return (
<div className="Counter" data-testid="Counter">
<h2> The count is: {count} </h2>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};
Counter.propTypes = {};
Counter.defaultProps = {};
export default Counter;
OpenAI will do its best to generate the component following the instructions provided in the --describe
flag while using the patterns supplied from the internal or custom component templates.
Okay, let's try another one.
npx generate-react-cli@alpha c GlobalNav -d "Create a navbar component with 1 logo named 'GRC' and 3 links: 'Home', 'About', 'Contact'"
and here's the output in src/components/GlobalNav/GlobalNav.js:
import React from 'react';
import PropTypes from 'prop-types';
import './GlobalNav.css';
const GlobalNav = () => (
<div className="GlobalNav" data-testid="GlobalNav">
<a href="#">GRC</a>
<ul>
<li>
<a href="#">Home</a>
</li>
<li>
<a href="#">About</a>
</li>
<li>
<a href="#">Contact</a>
</li>
</ul>
</div>
);
GlobalNav.propTypes = {};
GlobalNav.defaultProps = {};
export default GlobalNav;
That's a wrap. I hope this integration will allow us to generate React components more efficiently, and we can still go in and make the necessary adjustments.
Again, please provide any feedback if you have any, and I would love to see some of the components that you generate with GRC+OpenAI.
Please share them with me on Twitter @arminbro.
License
Generate React CLI is an open source software licensed as MIT.