[001.1] Setting up a React App

Setting up a React App
[05.03.2017]

In the last
twoepisodes,
we built a Rails API for a Custom Form Builder. Today we will start a React
application that will allow us to display and submit forms generated in that
API. We'll start the project using Create React
App. This is a
boilerplate made by Facebook to rapidly create applications using webpack and a
series of scripts to aid development. Let's get started.

Project

The first thing we will do is install create-react-app globally on our machine.

yarn global add create-react-app

Then we will use it to create our app. Our app's name will be formulae_react:

create-react-app formulae_react

This will generate a new React app for us with sensible defaults. We can change
into the directory and run yarn start to see the initial app in the browser.
By default, it will run on port 3000:

This is just a typical React component, rendering some boilerplate.
create-react-app also generated a test:

vim src/App.test.js

importReactfrom'react';importReactDOMfrom'react-dom';importAppfrom'./App';it('renders without crashing',()=>{constdiv=document.createElement('div');ReactDOM.render(<App/>,div);});

This is a pretty barebones test - it verifies that the App component renders
successfully. Let's run the tests:

yarn test

This ran the test, and now it's in watch mode - when we change a file and save
it, the corresponding tests will be run for us here. Let's exit with q.

Adding Flow

Before we move on, we'll be introducing flow to our
project. Flow is a static type checker for JavaScript. It will allow us to
annotate various expressions, and ensure we're passing the right types of
arguments to our functions.

importReactfrom"react";importReactDOMfrom"react-dom";importRespondToFormfrom"./RespondToForm";it("renders without crashing",()=>{constdiv=document.createElement("div");ReactDOM.render(<RespondToForm/>,div);});

Then we'll verify the tests still pass:

yarn test

They do. Now we can change the index.js file to load RespondToForm instead
of App:

This is fine as a starting point, but we'd really like to prove to ourselves
that it's rendering an h2. We'll introduce
Enzyme, which provides us an easy way to
render components in our tests and assert things about them. Enzyme provides a
shallow function for rendering a single layer of our React application.

We'll install the package as a development dependency. We also need to bring in
the react-test-renderer package because enzyme wants it to be available:

yarn add --dev enzyme react-test-renderer

Then we'll update our test to shallow-render our component, and use Enzyme's
API to assert that the text() of our rendered component contains the title
property we pass in.

importReactfrom'react'importReactDOMfrom'react-dom'import{shallow}from'enzyme'importSectionfrom"./Section";it('renders without crashing',()=>{constdiv=document.createElement('div')ReactDOM.render(<Section/>,div)})it('renders the title in an h2',()=>{constdiv=document.createElement('div')consttitle="Second"constsubject=shallow(<Sectiontitle={title}/>)
expect(subject.text()).toMatch(/Second/)})

Let's run our tests.

yarn test

They pass. So we've got a slightly more interesting test working.

Next, let's introduce flow. To do this, we'll open the RespondToForm file and
add a comment at the top that tells flow to check this file:

vim src/components/RespondToForm.js

// @flow// ... the rest of the file ...

I've got flow integrated into my editor, so I'll see any type errors
immediately when I save a file. In this case, there are no errors.

Right now this component doesn't take any arguments. We want to pass it a form
prop that could contain multiple sections, and render each section. Let's see
what that looks like:

Now when we save the file, flow warns us that we haven't described what type
we expect to be passed in as our props variable. We'll define a Props type that looks
like an object with a form key containing what we'll call a FormType, which
contains a sections key containing an array of what we'll call a
SectionType:

Now flow isn't mad any more. If we run the tests now, they'll fail as we're
not passing the appropriate props to the component. We'll pass the appropriate
shape of data in, then we'll add a test to verify that we produce 2 Section
components when we pass 2 sections in:

sign up for full access

Meet your expert

I've been building web-based software for businesses for over 18 years. In the last four years I realized that functional programming was in fact amazing, and have been pretty eager since then to help people build software better.