Adding new features to your React project? Most probably you would be rewriting or copy-pasting the boilerplate code if I am not wrong. Wait, you don’t need to do all this stuff every time when adding new features. Generally, the steps that we need to follow to set up a component are to write at least a few lines of code such as the imports and declaration of the component that can be either a functional, stateful, or pure component. So, we can say that adding a new feature to our project usually involves following a bunch of repetitive steps such as adding the styles, components, test suites, and other existing configurations.
Problems faced while copying the code is selecting the ideal component from the project so that modifications can be done to make the component as per the new features. But it would be overhead to rename all the things that do reference the existing features and basic configuration. Or let's assume we are creating new files from scratch -- it would be very time-consuming in setting up all the files with similar naming conventions and importing the related files. Of course, that can affect the developer’s productivity.
Let’s note down the steps that we might need to follow when adding a new component/feature in our project.
- Creating a folder with the name of the component (keeping in mind the case to use).
- Creating an index file with the basic content for the component.
- Creating a file for adding the stylings to the component.
- Creating a JSON file for mock data for the component.
- Creating a test file for the component.
Yeah, these are the basic required steps to start working on the new component. And other important steps include finding an ideal file for every new feature to be added so that the code can be copy-pasted from that file and importing the related files.
So, how about an idea of setting up a template that contains the basic configurations and the boilerplate code to start with? A process known as scaffolding can be used to generate boilerplate code by creating templates. For example, if you have worked with any of the .NET project with MVC architecture visual studio provides you the basic files created when we select the template for the MVC architecture. Here comes hygen in light.
Create React App
Create React App is a package provided by Facebook when you want to focus on your code rather than focusing on configuring a React application with tools like Webpack or Babel in your code. Every basic and necessary thing to start working on react application is preconfigured so that we can focus on the code rather than spending time in development and production builds configuration of the project.
So, we can say that Create react app is not mandatory for creating react applications but using it would make it a lot easier for us to focus on code rather than spending time to configure the solution.
In simple language, we can say that hygen is a code generator that can generate code in any language. Hygen basically uses EJS for writing templates and JS for prompts. Hygen helps to generate code and avoid the manual work needed for the codebase.
I have used the npm to work with hygen in my project, but you can also use yarn to work with it. Let's have a look at the steps for installing hygen in our solution.
Stepping towards installation
To install hygen we use the command shown below,
Initialize hygen using the command given below, initialize hygen only once in your project i.e. below command needs to be run once for a project.
On initializing hygen a folder “_templates” is created at the root level. _templates contains a folder generator that includes three subfolders with the names Help, new, and with-prompt including some examples.
Understanding the code
The component.ejs.t file has the code for generating the component, in our case it is a functional component with the name of the component dependent on the name provided by the user.
Here the formatter section contains the name and path of the file that we want to generate using our templates. Matching lines “---” is included to the top and the bottom, in between we can define our metadata.
We have used the command
- hygen components new --name FirstComponent
Our formatter will be built as,
to: src/components/FirstComponent/DemoComponent.js
Let's run the command for generating the code using the templates that we have created. Command is for generating the component inside the “new” folder with the name provided in the command.
Command
- hygen components new –name FirstComponent
The folder structure of the new component created will be as,
The lines “---” below and above the formatter are the lines that contain the YAML inside it. The YAML included in the metadata of the templates.
The code generated from this template will be as shown in the code snippet below. Here “to:” describes the path where the file should be created. The path of the file will first check whether the path exists or not, if not the required folders will be created. For example, while running the command initially we won’t be having any such folder as components or FirstComponent so these folders will be created for the required component file that can be placed at the correct path.
The path of the file would be: “..\src\components\FirstComponent\index.js”
Template: Index.ejs.t
- ---
- to: src/components/<%= h.inflection.classify(name) %>/index.js
- ---
-
- <% componentName = h.inflection.classify(name) -%>
- export { default } from './<%= componentName %>';
The index file would be the entry point of the folder that has been created i.e. FirstComponent in this case.
Code: index.js
- export { default } from './FirstComponent';
The template Component will be used to create the container file for the new component created. The code that we can include is the necessary import for the main component and the styles that will be used for the main component as well as the child component. We can also include the test file imports as adding the unit tests for the component.
Template: Component.ejs.t
- ---
- to: src/components/<%= h.inflection.classify(name) %>/<%= h.inflection.classify(name) %>.js
- ---
-
- <% componentName = h.inflection.classify(name) -%>
- import React, {useState} from 'react';
- import styles from './styles';
- const <%= componentName %> = () => (
- <div className={<%= componentName %>}>
- <h3><%= componentName %> Component</h3>
- </div>
- );
- export default <%= componentName %>;
FirstComponent.js file will be the main component file or we can say that container of the component.
Code: FirstComponent.js
- import React, {useState} from 'react';
- import styles from './styles';
- const FirstComponent = () => (
- <div className={FirstComponent}>
- <h3>FirstComponent Component</h3>
- Hello
- </div>
- );
- export default FirstComponent;
The template style is used to create the styles for the component.
Template: style.ejs.t
- ---
- to: src/components/<%= h.inflection.classify(name) %>/styles.js
- ---
-
- <% componentName = h.inflection.classify(name) -%>
- import { css } from 'react-emotion';
- import { colors } from '../../styles';
- import { mediaQuery } from '../../styles/breakpoints';
-
- export default {
- container: css`
- margin-top: 0;
- color: ${colors.black};
- ${mediaQuery.medium(css`
- color: ${colors.sky};
- `)}
- `
- }
The styles file can include some of the important things like the main class that helps us avoid styling inconsistencies with other components. For example, we can have a main class as per the name of the component and that main class can include the other styles. We can also include the media queries as per the requirement of the component.
Code: Styles.js
- import { css } from 'react-emotion';
- import { colors } from '../../styles';
- import { mediaQuery } from '../../styles/breakpoints';
-
- export default {
- container: css`
- margin-top: 0;
- color: ${colors.black};
- ${mediaQuery.medium(css`
- color: ${colors.sky};
- `)}
- `
- }
The template test is used to create a file for the component. It includes creating a separate folder for the test files.
Template: test.ejs.t
- ---
- to: src/components/<%= h.inflection.classify(name) %>/__tests__/<%= h.inflection.classify(name) %>.test.js
- ---
-
- <% componentName = h.inflection.classify(name) -%>
- import React from 'react';
- import { shallow } from 'enzyme';
- import <%= componentName %> from './<%= componentName %>';
-
- describe("<%= componentName %>", () => {
- it("should render the component", () => {
-
- });
-
- });
A test file will be created with the name of the component as the name of the test file. Adding unit tests to our code makes it more efficient and less prone to bugs.
Code: FirstComponent.test.js
- import React from 'react';
- import { shallow } from 'enzyme';
- import FirstComponent from './FirstComponent';
-
- describe("FirstComponent", () => {
- it("should render the component", () => {
-
- });
-
- });
Summary
Using generators in our project helps us to save time with better developer experience and also helps us to maintain the coding standards. Using generators helps us save the number of clicks and keystrokes required for setting up the project. It also helps us to focus more on the project features rather than spending time to find the boilerplate code for the setup. You can also use generators if you have been working with multiple team members and you want to maintain the standards of coding in the project.
Generators are an investment that save time, in the long run, the benefit will be better developer experience and improved code standards. Give it a try.
Ideas???
There are so many repetitive steps that we follow while adding new features or starting a new project. I would love to hear the steps or the workflow that you follow to minimize repetitive work and focus more on the features than on setting up the coding standards, designing the workflows for the team, and maintaining the consistent structure of components across the team. Wouldn't it be good to have ideas about focusing more on features than ideas?