Skip to content

jgreen01/jngrn

Repository files navigation

Site based off of Eric Elliott's React Pure Component Starter

React Pure Component Starter

Circle CI

React 0.14 introduced the ability to use pure functions as components. The react team calls them functional components in their announcement. The rest of the world calls them pure components.

Getting Started

Clone the repo & install:

git clone git@github.com:ericelliott/react-pure-component-starter.git
cd react-pure-component-starter
npm install

Optionally set environment variables HOST and PORT, start the dev server and follow instructions: As of this writing:

Cloud9 (c9.io) HOST='0.0.0.0' PORT=8080

Nitrous.io HOST='0.0.0.0' PORT=3000

The environment variables can be set locally in bash terminal using export (e.g., export PORT=8080).)

npm start

In another terminal window, start the dev console for lint/test feedback when you save files:

npm run watch

NOTE: Currently not supported on Windows.

Pure Component Factories

Pure component factories let you inject your React instance into the component so that you can share a single React instance across your entire app -- even if you load React from CDN for client use (which may save lots of users time, because they'll already have it cached locally).

I recommend that all your reusable components export factories and take a React instance as a dependency. It's really easy. A regular pure component looks like this:

export default (props) => <h1>{ props.title }</h1>;

To add the factory wrapper for React injection, just insert another arrow function with a React parameter:

export default React => (props) => <h1>{ props.title }</h1>;

If you're still confused, this desugars to this ordinary ES5:

"use strict";

module.exports = function (React) {
  return function (props) {
    return React.createElement(
      "h1",
      null,
      props.title
    );
  };
};

Yeah. Arrow functions rock.

In case you blinked and missed it, the ES6 factory again:

export default React => (props) => <h1>{ props.title }</h1>;

As you can see, React is a parameter, but it doesn't get explicitly mentioned anywhere in the rest of the line... and there are no other lines. So why do we need it?

Remember that JSX is not real DOM markup. There's a compile step that transforms the JSX code into this:

React.createElement(
  "h1",
  null,
  props.title
);

That compiled output uses React, and expects it to be available inside the component scope, so you need to pass React in, even though it's not obvious that it's being used.

Unit Testing React Components

I recommend Test Driven Development (TDD). Write your tests first. Learn how to write unit tests: Read 5 Questions Every Unit Test Must Answer.

Unit testing React components is a lot easier than it sounds. Let's look at the imports for the title example in test/components/title/index.js:

import React from 'react';
import reactDom from 'react-dom/server';
import test from 'tape';
import dom from 'cheerio';

The first line pulls in React, which you'll need to pass into the component factory. As we already mentioned, it's also required for the JSX to work.

react-dom

import reactDom from 'react-dom/server'

React 0.14 split the DOM utilities out of the main React package. There are several reasons for this change. One of the more important reasons is that React is not always used to render HTML DOM. For instance, Netflix uses it to render to an in-house rendering library called Gibbon, and Facebook has another framework called React Native, which lets you build native user interfaces on mobile using JavaScript, sharing much of the same code and architecture with your web and server apps.

So, react's DOM utilities now live in react-dom, which is split in two:

  • react-dom/server
  • react-dom/client

Tape

import test from 'tape';

Tape is a great testrunner because it keeps everything very simple. For details, read Why I Use Tape Instead of Mocha, and So Should You.

Cheerio

import dom from 'cheerio';

Cheerio is a jQuery-like API for querying and manipulating DOM nodes. If you know jQuery, you know Cheerio.

I use it for testing React component outputs. Much better than the peculiarly named .findRenderedDOMComponentWithClass() and .scryRenderedDOMComponentsWithClass() (I swear, I'm not making these up).

It does not need JSDom. It does not need Selenium web driver. It does not need a browser. Not even PhantomJS. Your DOM is just DOM. Save the browser wrangling for your critical path functional tests. Keep your component unit tests simple.

"Simplicity is a feature." ~ Jafar Husain (Netflix, TC39)

About

Personal Website.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published