DEV Community

Ben Tyler
Ben Tyler

Posted on • Edited on • Originally published at lostcreekdesigns.co

3

Auto-Generating a React Component with Intelligent Boilerplate

The Problem

Over the holidays I refactored my personal site and built a lightweight design system for myself. This meant creating a whole lot of new components. Due to my organizational preference for components, it meant that for each new component I needed to create a new directory, index.tsx, [ComponentName].tsx, and [ComponentName].stories.tsx file. And then to round the process out, I would copy and paste some boilerplate into each file. As the design system grew, so did my impatience with this process.

The Solution

My initial instinct was to create a VSCode snippet for each file type. This solved half of the problem but the whole process still lacked some solid ergonomics. I remembered reading a post from Joel Hooks on how he streamlined the process of creating a new blog post with a npm script (worth a read in my opinion). I thought could probably do something pretty similar for generating components. This ended up being the ticket.

The solution was relatively straightforward largely because I did not need this thing to be bulletproof (can you spot how easily this thing can break?). My favorite thing about this whole script is how it produces "intelligent" boilerplate. Whatever you provide for the componentName arg will be used to generate the directory and file names as well as the names for various structures in the code. Not having to copy and paste boilerplate and update variable names and exports is the real time saver in my opinion. The last thing I did was add a new script to my package.json called create:component.

Usage

From the root of the project I can now just open up my terminal and run something like yarn create:component MapHeader and in less than a second I will have all of my files and intelligent boilerplate.

The Snippets

// createComponent.js
const fs = require("fs")

// grab the component name from the command
const componentName = process.argv[2]

// boilerplate for components/${componentName}/index.tsx
const indexTemplate = `export { ${componentName} } from "./${componentName}"`

// boilerplate for the actual component, components/${componentName}
const componentTemplate = `
import React from 'react'

export type ${componentName}Props = {}

export const ${componentName}: React.FC<${componentName}Props> = (props) => {
  return (

  )
}
`

// boilerplate for the component story
const storyTemplate = `
import React from 'react'
import { Story, Meta } from '@storybook/react'
import { ${componentName}, ${componentName}Props } from './${componentName}'

export default {
  title: '/${componentName}',
  component: ${componentName},
  args: {}
} as Meta

const Template: Story<${componentName}Props> = args => <${componentName} {...args} />

export const Default = Template.bind({})
Default.args = {}
`
// create a directory for the component
fs.mkdirSync("./src/components/" + componentName)

// create files and drop in boilerplate
fs.writeFileSync(
  `./src/components/${componentName}/index.tsx`,
  indexTemplate.trim()
)
fs.writeFileSync(
  `./src/components/${componentName}/${componentName}.tsx`,
  componentTemplate.trim()
)
fs.writeFileSync(
  `./src/components/${componentName}/${componentName}.stories.tsx`,
  storyTemplate.trim()
)
Enter fullscreen mode Exit fullscreen mode
// package.json
"scripts": {
    "build": "gatsby build",
    "create:blog": "node scripts/createBlogPost.js",
    "create:component": "node scripts/createComponent.js",
    "develop": "gatsby develop",
    "format": "prettier --write \"**/*.{js,jsx,json,md}\"",
    "start": "npm run develop",
    "serve": "gatsby serve",
    "storybook": "start-storybook -p 6006",
    "storybook:build": "build-storybook"
  },
Enter fullscreen mode Exit fullscreen mode

If you have any questions or comments please reach out below! If you found this post useful, please retweet or share! You also can sign up for updates for whenever I release a new post.

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

Top comments (0)

Eliminate Context Switching and Maximize Productivity

Pieces.app

Pieces Copilot is your personalized workflow assistant, working alongside your favorite apps. Ask questions about entire repositories, generate contextualized code, save and reuse useful snippets, and streamline your development process.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay