React Flow

Introduction

Flow is a static type checker for your JavaScript code. It checks your code for errors through static type annotations. With the help of these types, Flow will make sure it works the way it does.

// @flow

onChange = (e: EventHandler) => {
    this.setState({ [e.target.name]: e.target.value })
  }

...

render () {
  const { year, set, cardNo } = this.state
  return (
    <form
      onSubmit={isCreate ? this.handleCreate : this.handleSubmit}
    >
      <InputText
        col
        label='Year'
        name='year'
        value={year}
        onChange={this.onChange(year)} // Error!
      />
    </form>
  )
}

Why We Use It

  • We want to check the structure of props that we send to our components.
  • We want to know the types of parameters our functions have and what they return.
  • It is easy to install and implement.

Installation

Please see Flow Installation for more detailed instructions.

Guidelines

The Flow background process monitors all Flow files that's why you have to indicate the following before any code in a JavaScript file for it to recognize that it uses Flow.

// @flow

/*
  your code here
*/

Or you can also use the form /* @flow */ as a flag instead of the one above.

You can annotate an Array of any Type by adding [] at the end

PrimitiveArray Counterpart
stringstring[]
booleanboolean[]
numbernumber[]
ProductTypeProductType[]

Node props such as children can be annotated as React.Node

Import React from 'react' // Don't forget to import React

type Props ={
  children: React.Node
}
const MyCard = ({children}: Props) => (
  <div className="Card">
    {children}
  </div>
)

Use PascalCase when defining a type alias

type OrderType = {
  refId: string,
  date: Date // Flow comes with Date type out of the box
}

type Props = {
  orders: OrderType[]
}

Avoid using any or mixed

Use Union Type if your variables have more than a single type

type ComponentProps = {
  children: string | number | React.Node
}

Examples

Functional Component

// Pascal Case when defining types
type Props = {
  header: string // Lower Case when using primitive types
}

const MyComponent = (props: Props) => (
  <div className='Header'>
    <h1>Mashup Garage</h1>
    <h2>{props.header}</h2>
  </div>
)
export default MyComponent

Class Component

A Class Component should by default have a type for State and Props. This will act as a reference to what data the component has and will save you from type related mistakes.

import React, { Component } from 'react'

type Props = {
  siteTitle: string
}

type State = {
  pageHeader: string
}

class MyComponent extends Component<Props, State> {
  state = { pageHeader: 'Home' }

  render() {
    return (
      <div className='Header'>
        <h1>{this.props.siteTitle}</h1>
        <h2>{this.state.pageHeader}</h2>
      </div>
    )
  }
}
export default MyComponent

Function

Every argument and every variable declared inside the function should have a type annotation.

export const validateEmail = (email: ?string) => {
  const errors = []
  if (!email) {
    errors.push('Email Required')
  } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(email)) {
    errors.push('Invalid Email Address')
  }
  return errors
}

References