Automate Your

React Workflow

@waterproofheart 

useReactNYC

June 2019

Monica Powell

Hi, I'm Monica!

I'm a Full Stack Engineer at Meetup && organizer of the React Ladies community.

 

 

 

@waterproofheart 

 


 Intro


React App Architecture
 


 What is Scaffolding?
 


Scaffolding Options


 DIY Scaffolding

 

Overview

@waterproofheart 

What does a typical React app look like?

Example modifed from: https://reactjs.org/docs/ 

  • UI components are the building blocks
  • Multiple components with test, CSS, translation, etc. files locally scoped 

@waterproofheart 

Adding components can be repetitive...

@waterproofheart 

Let's just copy and paste everything we need!

 

@waterproofheart 

        Let's use 

templates

mail merge

@waterproofheart 

Is it worth the time?

@waterproofheart 

What is scaffolding?

  • Generating starter-code based on templates
  • Boilerplate code that is shared between components that share conventions.
  • Minimial Viable Component != ready for production.

 

 

@waterproofheart 

Separate Templates Based on Type of Component

import React, { Component } from 'react';

export class MyComponent extends Component {
  render() {
    return (
      <div></div>
    );
  }
}
const MyComponent = (props) => {
    return (
      <div></div>
    );
}

Class

Functional

@waterproofheart 

Benefits of Scaffolding

 

  • Reduce time to generate new projects or components.
  • less error-prone than copy & pasting & editing
  • encourage consistency and implementation of  design patterns

@waterproofheart 

Where should translations for this component live?

What's the current source of truth for our code standards?

Does every component go in the same folder?

How are components named?

What style should JavaScript components be written in?

Scaffolding Can Answer FAQs

 

@waterproofheart 

What's the fastest way to get up and running with scaffolding?

@waterproofheart 

 

  • React-boilerplate reduces overhead for developing a React app optimized for production

  • One-size-fits-all approach can unecessarily increase complexity and dependencies

  • Includes CLI tool to scaffold React components, containers, routes, selectors, etc.
2
2
2
3
 

@waterproofheart 

React-Boilerplate

`yarn run generate` 

@waterproofheart 

  • React Ignite is similar to React-boilerplate but for React Native
  • Includes various customizable tools to jump start the creation of React Native applications
  •  "Ignite speeds up your app development by over two weeks on average."
 

@waterproofheart 

Code Generators

More lightweight scaffolding solutions than

React Boilerplate and React Ignite

 

@waterproofheart 

PlopJS

  • PlopJS is a microgenerator, and is used under the hood in React-Boilerplate

  • It generates files based on user input via a Command Line Interace (CLI).

  • Minimal setup required

  • plopjs.com

@waterproofheart 

PlopJS 

  • Handlebars templating language

  • (similar to Mustache)

+

  • Inquirer.JS is a a collection of common interactive command line user interfaces.

@waterproofheart 

Let's generate Kawaii Components

@waterproofheart 

Structure of Kawaii Components

 

@waterproofheart 

import { Backpack } from 'react-kawaii';

const Example = () => <Backpack size={ 300 } mood="lovestruck" color="#EC4067" />;

What we want to generate

/**
*
* LovestruckBackpack
* Description: This component is a lovestruck Backpack.
*/

import React from 'react';
import { Backpack } from 'react-kawaii'

function LovestruckBackpack() {
return (
<Backpack size={ 200 } mood="lovestruck" color="#EC4067" />

);}

LovestruckBackpack.propTypes = {};

export default LovestruckBackpack;

@waterproofheart 

Code

Component

Getting started with Plop

Create a handlebars template

1
/**
*
* {{properCase mood}}{{properCase kawaiiComponent}}
* Description: This component is a {{mood}} {{kawaiiComponent}}.
*/

import React from 'react';
import { {{kawaiiComponent}} } from 'react-kawaii'

function {{properCase mood}}{{properCase kawaiiComponent}}() {
return (
<{{kawaiiComponent}} size={ {{size}} } mood="{{mood}}" color="{{color}}" />

);
}

{{properCase mood}}{{properCase kawaiiComponent}}.propTypes = {};

export default {{properCase mood}}{{properCase kawaiiComponent}};

@waterproofheart 

Getting started with Plop

Plop is essentially a node module that accesses the plop API through a plop object that is passed in as a parameter.

 

module.exports = function (plop) {
    // create your generators here
    plop.setGenerator('basics', {
        description: 'this is a skeleton plopfile',
        prompts: [], // array of inquirer prompts
        actions: []  // array of actions
    });
};

@waterproofheart 

What should we import?

Let's add out first prompt to select which Kawaii component we want to import

{
        type: "list",
        name: "kawaiiComponent",
        message: "Which Kawaii component would you like to generate?:",
        choices: [
          "Backpack",
          "Browser",
          "Cat",
          "CreditCard",
          "File",
          "Ghost",
          "IceCream",
          "Mug",
          "Planet",
          "SpeechBubble"
        ]
      },

@waterproofheart 

What color do we want?

Let's add out first prompt to select which color we want our component to be

  {
        type: "list",
        name: "color",
        message: "What color should the component be:",
        choices: ["eggplant", "mint", "bubblegum pink", "purple", "lime"],
        filter: colour =>
          ({
            "eggplant": "#2E294E",
            "mint": "#1B998B",
            "bubblegum pink": "#EC4067",
            "purple": "#9A39AB",
            "lime": "#C5D86D"
          }[colour])
      },

@waterproofheart 

Let's select a size!

Let's create a prompt for what size our component should be

  {
        type: "list",
        name: "size",
        message: "What size should the component be:",
        choices: ["extra small", "small", "medium", "large", "extra large"],
        filter: val =>
          ({
            "extra small": 100,
            "small": 200,
            "medium": 300,
            "large": 500,
            "extra large": 800
          }[val])
      }

@waterproofheart 

What mood are we in?

 

Let's add a prompt to select which the mood we want our component to have

 {
        type: "list",
        name: "mood",
        message: "Mood:",
        choices: [
          "sad",
          "shocked",
          "happy",
          "blissful",
          "lovestruck",
          "excited",
          "ko"
        ]
      }

@waterproofheart 

Copy & Populate Templates

Now what do we want to do with the user input we collected? 

actions: [
      {
        type: "add",
        path: "src/{{properCase mood}}{{properCase kawaiiComponent}}.jsx",
        templateFile: "src/plop-templates/kawaii-component-template.hbs"
      },
      {
        type: "add",
        path: "src/{{properCase mood}}{{properCase kawaiiComponent}}.test.jsx",
        templateFile: "src/plop-templates/test.hbs"
      }
]

@waterproofheart 

Finished Plop File

Now what do we want to do with the user input we collected?

module.exports = function(plop) {
  plop.setGenerator("Generate Kawaii Component", {
    description: "Templates from the React Kawaii library ",
    prompts: [
      {
        type: "list",
        name: "kawaiiComponent",
        message: "Which Kawaii component would you like to generate?:",
        choices: [
          "Backpack",
          "Browser",
          "Cat",
          "CreditCard",...
        ]
      }, // truncated for example...
    ],
    actions: [
      {
        type: "add",
        path: "src/{{properCase mood}}{{properCase kawaiiComponent}}.jsx",
        templateFile: "src/plop-templates/kawaii-component-template.hbs"
      },
      {
        type: "add",
        path: "src/{{properCase mood}}{{properCase kawaiiComponent}}.test.jsx",
        templateFile: "src/plop-templates/test.hbs"
      }
  ]
  });
};

@waterproofheart 

 Autoimport Component

{
        type: "append",
        path: "src/index.js",
        pattern: /import ".\/index.css"[;]/,
        unique: true,
        templateFile: "src/plop-templates/import-component-template.hbs"
      },

      {
        type: "append",
        path: "src/index.js",
        pattern: /<\/h1>/,
        unique: true,
        templateFile: "src/plop-templates/render-component-template.hbs"
      }

@waterproofheart 

import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
// import generated component here

ReactDOM.render(
  <div>
    <h1>Demo</h1>
   <!-- reference imported component here -->
 </div>,

  document.getElementById("root")
);

plopfile.js

index.js

 Autoimport Component

@waterproofheart 

// src/plop-templates/import-component-template.hbs
import {{properCase mood}}{{properCase kawaiiComponent}} from './{{properCase mood}}{{properCase kawaiiComponent}}';

// src/plop-templates/render-component-template.hbs
<{{properCase mood}}{{properCase kawaiiComponent}} />,

Demo

@waterproofheart 

Getting started with Plop

/**
*
* LovestruckBackpack
* Description: This component is a lovestruck Backpack.
*/

import React from 'react';
import { Backpack } from 'react-kawaii'

function LovestruckBackpack() {
return (
<Backpack size={ 200 } mood="lovestruck" color="#EC4067" />

);}

LovestruckBackpack.propTypes = {};

export default LovestruckBackpack;

@waterproofheart 

 Getting Started with Plop Summary

@waterproofheart 

1. Create handlebar templates

2. Create a plopfile and import plop

3. Define generator:

  • description
  • prompts
  • actions to carry out

Challenge

  • Create a CLI tool with conditional logic using Plop
  • Some ideas:

    • generate metadata for Gatsby blog posts and pages
    • generator components from a component library that you use regularly

 

1

Thank You!

 

 

Twitter: @waterproofheart

 

aboutmonica.com || monica.dev

 

 meetup.com/React-Ladies/

https://github.com/M0nica/generate-react-components

github.com/M0nica/generate-kawaii-components

Automate React Workflow at useReact NYC

By m0nica

Automate React Workflow at useReact NYC

Do you find yourself copying and pasting the same boilerplate React code in multiple files every time you create a new component? Imagine a world without copy and paste. How much time would that cost you? This talk walks through how to create a command-line interface (CLI) tool that generates React component files.

  • 889