So you are working in your React app, and it comes the time to create a new component, you already have your ritual down. Go to the components folder, create an index file, create another file for styles and finally one more for testing because you are cool. After all of this, you still have to connect these files and write enough code to make them run. You do this every time... every time.
I am assuming a lot, but if this is actually you I have good news!
What if I told you there is way to automate this boring and tedious process?
Trust me, these next 10 minutes are going to change your life. Let me introduce you to plop.js.
What is Plop.js?
In their own words, it's a tool that saves you time and helps you build new files with consistency.
How does it work?
It's easier than you think, otherwise I wouldn't be writing about it lol. You create file templates and configure a very simple cli.
Let's start
First, let's clone this simple react app, it has nothing but just a basic react setup.
git clone git@github.com:ivanms1/parcel-template.git
And navigate to it
cd parcel-template
Now let's install plop, on the terminal type:
yarn add plop
# or
npm install plop
The Generator
Next, on the root folder, create a file called plopfile.js
and add the following content inside.
module.exports = function (plop) {
plop.setGenerator("component", {
description: "Create a component",
prompts: [
{
type: "input",
name: "name",
message: "What is this component's name?",
},
{
type: "input",
name: "element",
message: "HTML element (div is default)",
default: "div",
},
],
actions: [
{
type: "add",
path: "src/components/{{pascalCase name}}/{{pascalCase name}}.tsx",
templateFile: "templates/Component.tsx.hbs",
},
],
});
};
We are basically configuring a cli to generate our files. plop.setGenerator
creates a generator, the first argument is the name of this generator and the second one is an object with some options where we can configure what to generate. Let's analyze the ones we will be using for this guide.
description
Pretty self explanatory, a description of your generator, for example: Generator of react components.
prompts
Series of steps, questions or instructions we give to the user in order to obtain certain information. Plop stores these in variables to use later in the template files.
In our case we are using input
type prompts to get
- The component's name.
- The component's html tag (div, button, a, etc), it defaults to div.
message
is text the user will see and has to interact with, generally a question or an instruction.
actions
After we've gather all the information need we then proceed to the actions, represented in an array. In our case we only have one action that creates a file.
Let's go a bit into more details with the actions, since it's where things actually happen. The add
action type creates a file, path
is simply the file path where the file is going to be created. The template
is sort of skeleton that will be used to create the file. Plop uses handlebars, a templating language that generates HTML and other text formats.
You might have noticed that we haven't created our template file, and yeah... we need to do that.
Creating our first template
On the root folder create a folder called templates
, and add a file named Component.tsx.hbs
with the following content.
import React from "react";
interface {{pascalCase name}}Props {}
const {{pascalCase name}} = () => {
return <div>{{pascalCase name}}</div>;
};
export default {{pascalCase name}};
As you could probably tell, we are creating a react typescript file, in handlebars the variables are inside double brackets ({{}}
). pascalCase
converts the name
variable, that we get from the prompts, to pascal case. So anywhere you see {{pascalCase name}}
, it will be replaced with the component's name.
So although this is cool, so far we are only creating a new file with some pre-written react code. There are snippet extensions that could do almost the same thing. Let's make this a bit more complete by also adding a style file.
Adding a style file
I am gonna be using stitches, a css-in-js library similar to styled components but with near-zero runtime, but feel free to use whatever you want.
Let's install the library first, on the terminal run:
yarn add @stitches/react
# or
npm install @stitches/react
Since we now want to create a style file as well, we need to add another action
to our generator. Update plopfile.js
with the following.
actions: [
{
type: "add",
path: "src/components/{{pascalCase name}}/{{pascalCase name}}.tsx",
templateFile: "templates/Component.tsx.hbs",
},
// new action here
{
type: "add",
path: "src/components/{{pascalCase name}}/styles.ts",
templateFile: "templates/styles.ts.hbs",
},
],
Pretty similar to the first action
, now we need to add a new template. Inside the templates
folder create a file called styles.ts.hbs
and add the following content.
import { styled } from '@stitches/react';
export const Styled{{pascalCase name}} = styled('{{element}}', {});
Just your basic css-in-js file, we create a styled component and export it.
Component.tsx.hbs
needs to be updated, so it imports and uses the new styled component we made. Now it should look like this:
import React from "react";
import { Styled{{pascalCase name}} } from "./styles";
interface {{pascalCase name}}Props {}
const {{pascalCase name}} = ({} : {{pascalCase name}}Props) => {
return <Styled{{pascalCase name}}>{{pascalCase name}}</Styled{{pascalCase name}}>;
};
export default {{pascalCase name}};
Now we are talking, plop is saving us some considerable time, generating not one, but two files.
The final step to see this in action is to add the following script to the package.json
.
"scripts": {
..., // rest of scripts
// add this at the end
"generate": "plop"
},
We are finally ready, sit down, relax and enjoy the show. On the terminal type
yarn generate
# or
npm run generate
Now let's create a Button
component.
With a button
tag of course.
If everything went well
Let's check the components folder.
import React from "react";
import { StyledButton } from "./styles";
interface ButtonProps {}
const Button = ({} : ButtonProps) => {
return <StyledButton>Button</StyledButton>;
};
export default Button;
The styles file is there as well.
import { styled } from '@stitches/react';
export const StyledButton = styled('button', {});
Pretty cool eh?
Ok maybe is not that cool, but hopefully by now you've realized the potential this has.
I've kept this simple and only created two files but you can keep playing with it and add as many generators and actions as you want. All people/teams are different and you can tweak plop to whatever convention/style you may have. You can even update existing files if for example you like having an index file for all your components. You can create generators for hooks, pages, helpers, etc, the sky is the limit.
I hope you liked this guide and let me know if you made any cool generators at @ivanms1
Thank you for taking the time to read this article, if you enjoyed it please like to support and follow for more.
Top comments (12)
this is great ! can we add import same route in router file also?
Yeah you can append code to existing file with
append
action. Something like thisbut also we need to create router :(
your linkedin? how can we connect
yeah, let's talk on twitter
Great! How can I add a dynamic path for files instead of the default src/components/?
Thank you!
You can change the path of the action to whatever you want, for example
or a dynamic value from the prompts
Great, and currently there is a package which is based on plop and preconfigured to create components in react, angular, vue and stencil. npmjs.com/package/plop-gen
Create any component and you can rename it and you can choose where you want to create it.
Good luck
Thanks
You're welcome!
Great article ivan.
Thanks Rohil!