2018 年 React と Redux のエコシステム総まとめ

Angular などの JavaScript フレームワークは大規模向けに設計されており、標準で多くのエコシステムが組み込まれています。

React は単なる View ライブラリです。そのため View ライブラリを補完するためのエコシステムの選択が必須となります。
**エコシステムを自由に組み合わせて開発者とプロジェクトに応じた理想的なフレームワークを作成する必要があるわけです。**
これは、小規模アプリケーションから大規模アプリケーションまでの様々な要件やニーズに対応できる柔軟性が高いことを意味していますが、エコシステムを選択するためのコストが必要となります。

下記では、筆者が最低限、導入を検討する余地があると考える主要な React のエコシステムとその簡単な概要を記載しています。

**筆者の独断と偏見で選択したエコシステムであることを考慮してお読みいただきたいです。**

既知のエコシステム (ほぼ知ってるかも...) は読み飛ばした方が良いかと思います。

**また、筆者自身、未熟のため間違った内容が多々あると思います。間違いを見つけた方は、コメントや編集リクエストを頂けると非常にありがたいです。**

## 読者対象

React と Redux のチュートリアルを一通りやり、React と Redux でアプリケーションを開発できる方を対象としています。
初心者の方も大歓迎ですが、HOC を書けるようになる前に Recompose を導入したり、ActionCreator や Reducer を書けるようになる前に redux-actions を導入したりすることは避けた方が良いです。

## React

もっと多くの React のエコシステム以外も知りたい方は[こちら](https://reactjs.org/community/debugging-tools.html "Debugging - React")を参照してください。

### Boilerplate

React の開発環境のセットアップを自力で行いたくない場合は、Boilerplate を利用するのが手っ取り早いです。
小規模から大規模向けまで、数多くの Boilerplate が存在しています。

#### [Create React App](https://github.com/facebook/create-react-app "facebook/create-react-app: Create React apps with no build configuration.")

既知の方が多いと思いますが、Create React App は、Facebook 製 React Boilerplate です。
ゼロ設定で React プロジェクトを始めることができます。
依存関係や設定を全て隠蔽してくれるのが特徴です。

以下のように簡単にプロジェクトを始めることができます。

```shell
npx create-react-app my-app
cd my-app
npm start
```

[ユーザーガイド](https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md)に従うことで、CSS プリプロセッサの追加や Flow の追加など、ある程度カスタマイズできます。

ユーザーガイドに記載されていないカスタマイズ (webpack の設定など) は、[`eject`](https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#npm-run-eject) する必要があります。
`eject` することで隠蔽されている依存関係や設定を全て書き出すことができます。

#### [Next.js](https://github.com/zeit/next.js "zeit/next.js: Framework for server-rendered or statically-exported React apps")

Next.js は、[Zeit](https://zeit.co "ZEIT") 製 React Boilerplate です。
SSR (Server Side Rendering) 機能も持つ Universal JavaScript プロジェクトを始めることができます。
SSR が必要な場合は、Create React App より Next.js を選択した方が良いでしょう。

Create React App 程ではないですが、以下のように簡単にプロジェクトを始めることができます。

```shell
npm install --save next react react-dom
```

_package.json_

```js
{
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start"
  }
}
```

_./pages/index.js_

```js
export default () => <div>Welcome to next.js!</div>
```

```shell
npm run dev
```

同じく Zeit 製の [Now](https://zeit.co/now "Now – Realtime Global Deployments") を利用することで、React アプリケーションを素早くデプロイすることができます。

#### [Gatsby](https://www.gatsbyjs.org "GatsbyJS")

Gatsby は、React ベースのモダンな静的サイトジェネレーターです。
静的なサイトや、Wordpress のような本格的な CMS を簡単に構築することができます。

Gatsby は以下のような特徴があります。

* React.js や webpack、モダンな JavaScript や CSS などの最新の Web テクノロジー。
* ヘッドレス CMS、SaaS サービス、API、データベース、ファイルシステムなどのデータを GraphQL を使用して取得する。
* 静的 PWA (Progressive Web Apps) を生成できる。
* 最速の Web サイトを構築する。

Gatsby を使用した際の速さを[公式ページ](https://www.gatsbyjs.org "GatsbyJS")から感じてください！
[React の公式ページ](https://reactjs.org "React - A JavaScript library for building user interfaces") なども Gatsby を使用して構築されています。

以下のようにプロジェクトを始めることができます。

```shell
npm install --global gatsby-cli
gatsby new gatsby-site
cd gatsby-site
gatsby develop
```

### Utilities

JavaScript の ES6 以降のネイティブ機能として、配列やオブジェクト、数値、文字列などを扱う関数が多数用意されています。
React においては、[リストを扱う際](https://reactjs.org/docs/lists-and-keys.html "Lists and Keys - React")に、`map()` 関数をよく利用したりするでしょう。
筆者は、[Lodash などのユーティリティライブラリは必要ない](https://qiita.com/ossan-engineer/items/ad5313d84da82c6ac421 "Lodash/Underscoreは必要ない（かも） - Qiita")とまでは言えませんが、極力利用したくはないタイプのポケモンです。
ES6 以降のネイティブ関数だけではカバーできない場合は、Lodash または Ramda の使用をお勧めします。

#### [Lodash](https://lodash.com "Lodash")

Lodash は、最も広く普及しているモダンな JavaScript ユーティリティライブラリです。

#### [Ramda](http://ramdajs.com/ "Ramda Documentation")

Ramda は関数型プログラミングスタイルのために設計された JavaScript ユーティリティライブラリです。
関数型プログラミングが好きで、関数型プログラミングでアプリケーションを開発したい場合は Ramda をお勧めします。

### Styling

React のスタイリングにおいて、[CSS in JS](https://speakerdeck.com/vjeux/react-css-in-js "React: CSS in JS // Speaker Deck") の基本概念を抑えておく必要があります。

**CSS in JS とは、 JavaScript を活用して以下のような CSS の多くの課題を解決するアプローチです。**

> 大規模化する CSS の問題点
>
> 1. グローバルネームスペース
> 1. 依存性
> 1. デッドコードの削除
> 1. 縮小
> 1. 定数の共有
> 1. 非決定論的な解決
> 1. 分離

React のスタイリングは、以下のように、CSS 定義を JavaScript オブジェクトで定義し、インラインスタイルで記述します。
style 属性に CSS をインラインで展開することにより、ローカルスコープを実現しています。

```jsx
const Button = ({ children }) => (
  <button style={{
    background: 'transparent',
    color: 'palevioletred',
  }}>
    {children}
  </button>
);
```

しかし、インラインスタイルは、擬似クラスや擬似要素、メディアクエリの定義はできないという問題があります。

この問題を解決している便利な CSS in JS ライブラリとして CSS Modules と Styled Components をお勧めします。Styled Components は最近特に人気があります。

#### [CSS Modules](https://github.com/css-modules/css-modules "css-modules/css-modules: Documentation about css-modules")

CSS Modules は、全てのクラス名がデフォルトでローカルスコープされる CSS ファイルです。もしくは、それを扱うための仕組みといったところでしょう。

[Reactを使ったモジュラーCSS : CSS-in-JSとCSS Module | プログラミング | POSTD](http://postd.cc/modular-css-with-react "Reactを使ったモジュラーCSS : CSS-in-JSとCSS Module | プログラミング | POSTD")

> これは、CSSモジュールの非常にシンプルな前提です。ReactコンポーネントはそれぞれのCSSファイルを取得し、そのCSSファイルはそのファイルとそのコンポーネントにスコープされています。構築時に、魔法が起こります。非常にシンプルで衝突の危険がないローカルクラス名が、自動生成された名前にマッピングされ、React内で使うためのJSオブジェクトリテラルとしてエクスポートされます。

```css
/* Thumbnail.css */
.image {
  border-radius: 3px;
}

/* Thumbnail.jsx */
import styles from './Thumbnail.css';
render() { return (<img className={styles.image}/>) }

/* Rendered DOM */
<img class="Thumbnail__image___1DA66"/>

/* Processed Thumbnail.css */
.Thumbnail__image___1DA66 {
  border-radius: 3px;
}
```

**CSS Modules によって BEM の命名規則による慣習的ローカルスコープ化やクラス名の複雑性の問題は解決されます。**

CSS Modules を実装したい場合は、以下のように webpack の css-loader のモジュールを有効にするだけです。

_webpack.config.js_

```js
loaders: ['style-loader', 'css-loader?modules']
```

以下は、CSS Modules を利用する前後のコンポーネントのサンプルです。

**Before:**

BEM の命名規約を用いてローカルスコープ化されたクラス名を命名しています。

_Button.css_

```css
.btn { /* ... */ }
.btn--success { /* ... */ }
.btn--danger { /* ... */ }
.btn--warning { /* ... */ }
.btn--info { /* ... */ }
```

_Button.jsx_

```jsx
const Button = ({ size, children }) => (
  <button className='btn btn--success'>
    {children}
  </button>
);
```

**After:**

グローバルスコープの問題を恐れること無く、命名規約なしに好きなクラス名を命名できます。

_Button.css_

```css
.normal { /* ... */ }
.success { /* ... */ }
.danger { /* ... */ }
.warning { /* ... */ }
.info { /* ... */ }
```

_Button.jsx_

```jsx
import styles from './style.css';

const Button = ({ size, children }) => (
  <button className=`${styles.normal} ${styles.success}`>
    {children}
  </button>
);
```

#### [Styled Components](https://www.styled-components.com "styled-components")

Styled Components は React コンポーネントとスタイルをまとめて記述できるようにする新たなライブラリです。
ES6 の[タグ付きテンプレートリテラル](https://www.styled-components.com/docs/advanced#tagged-template-literals) と ネスティングなどを含めた [CSS 全機能](https://www.styled-components.com/docs/api#supported-css) を組み合わせてコンポーネントをスタイリングします。

CSS Modules は className を使用してコンポーネントとスタイルをマッピングする必要がありましたが、Styled Components はその必要がありません。

以下は、Styled Components を利用する前後のコンポーネントのサンプルです。

**Before:**

_Button.jsx_

```jsx
const Button = ({ primary, children }) => (
  <button style={{
    borderRadius: '3px',
    padding: '0.25em 1em',
    margin: '0 1em',
    background: primary ? 'palevioletred' : 'transparent',
    color: primary ? 'white' : 'palevioletred',
    border: '2px solid palevioletred',
  }}>
    {children}
  </button>
);
```

**After:**

Props を Styled Components に渡すことができたり、再利用できたりと様々な機能を提供しています。

_Button.jsx_

```jsx
import styled, { css } from styled-components;

const Button = styled.button`
  border-radius: 3px;
  padding: 0.25em 1em;
  margin: 0 1em;
  background: transparent;
  color: palevioletred;
  border: 2px solid palevioletred;

  ${props => props.primary && css`
    background: palevioletred;
    color: white;
  `}
`;
```

#### [Classnames](https://github.com/JedWatson/classnames "JedWatson/classnames: A simple javascript utility for conditionally joining classNames together")

Classnames は classNames を条件付きで結合するためのシンプルな JavaScript ユーティリティです。
これは、React の 公式 Addons だった `classSet` の代替です。

以下は、Classnames を利用する前後のコンポーネントのサンプルです。

**Before:**

条件付きクラスを含む場合は、if 文で制御する必要があります。

_Button.jsx_

```jsx
const Button = ({ size, children }) => {
  let classNames = ['btn'];

  if (size === 'large') {
    classNames.push('btn-lg');
  }

  if (size === 'small') {
    classNames.push('btn-sm');
  }

  return (
    <button className={classNames.join(' ')}>
      {children}
    </button>
  );
};
```

**After:**

条件付きクラスをオブジェクトとして表現できるためシンプルになります。

_Button.jsx_

```jsx
import classNames from 'classnames';

const Button = ({ size, children }) => {
  const classNames = classNames({
    'btn': true,
    'btn-lg': size === 'large',
    'btn-sm': size === 'small'
  });

  return (
    <button className={classNames}>
      {children}
    </button>
  );
};
```

Classnames は CSS Modules 及び Styled Components にも使用することができます。

### Type Checking

React での型チェックでは、[PropTypes](https://github.com/facebook/prop-types "facebook/prop-types: Runtime type checking for React props and similar objects") という機能を使います。
PropTypes は、コンポーネントの Props を型チェックします。

以下のように記述します。

```jsx
import PropTypes from 'prop-types';

class Greeting extends React.Component {
  render() {
    return (
      <h1>Hello, {this.props.name}</h1>
    );
  }
}

Greeting.propTypes = {
  name: PropTypes.string
};
```

間違った型の Props がコンポーネントに渡されると、アプリケーションの実行中にエラーメッセージを表示します。

静的型チェッカーを使用することで、コードを実行する前に型の問題を特定できます。また、自動補完などの機能を追加することで、開発者のワークフローを改善することもできます。

Flow と TypeScript どちらを導入するか選択する際は、[こちらの記事](https://github.com/niieani/typescript-vs-flowtype "niieani/typescript-vs-flowtype: Differences between Flowtype and TypeScript 2.6 -- syntax and usability")が役立つかもしれません。

#### [Flow](https://flow.org/ "Flow: A Static Type Checker for JavaScript")

Flow は、Facebook 製の JavaScript コードの静的型チェッカーです。変数宣言や、関数の引数や返り値に型定義 (アノテーション) することで、事前に型チェックすることができます。

[flow-remove-types](https://github.com/flowtype/flow-remove-types "flowtype/flow-remove-types: 🚿 Removes Flow type annotations from JavaScript files with speed and simplicity.") でアノテーションを取り除くこともできます。

#### [TypeScript](https://www.typescriptlang.org "TypeScript - JavaScript that scales.")

TypeScript は、Microsoft 製の altJS です。これは、JavaScript の静的型付きスーパーセットであり、独自のコンパイラを含みます。

[DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped "DefinitelyTyped/DefinitelyTyped: The repository for high quality TypeScript type definitions.") と [flow-typed](https://github.com/flowtype/flow-typed "flowtype/flow-typed: A central repository for Flow library definitions") を比較すると一目瞭然なのですが、サードパーティライブラリの型定義ファイルが TypeScript の方が圧倒的に充実しています。

### State Management

React は、State を保持する `this.state` と、State を更新する `this.setState()` を使い、コンポーネント内で State を管理する (ローカル State) ことができます。
基本的に、State を配置するコンポーネントは[State を必要とする全てのコンポーネントの最上層にいる単一のコンポーネント](https://reactjs.org/docs/thinking-in-react.html#step-4-identify-where-your-state-should-live)です。

アプリケーションがスケールしていき複雑化することで、[かつてないほどの多くの State](https://redux.js.org/docs/introduction/Motivation.html) を管理しなければなりません。
これを解決するために、Redux や MobX のような State を外出しして一元管理する (グローバル State) ライブラリを使用することをお勧めします。
グローバル State 管理ライブラリが必要かどうかは[こちら](https://medium.com/@dan_abramov/you-might-not-need-redux-be46360cf367 "You Might Not Need Redux – Dan Abramov – Medium")を参照して決定してください。

Redux と MobX どちらを導入するか選択する際は、[こちらの記事](https://www.webprofessional.jp/redux-vs-mobx-which-is-best "Reactのステート管理にはReduxとMobXのどちらを使うべきか - WPJ")が役立つかもしれません。

#### [Redux](https://redux.js.org "Read Me · Redux")

Redux は React Community によって作られた State 管理ライブラリです。
React の State 管理ライブラリの中で最も人気があります。

Redux に React をブリッジングする場合は、[React Redux](https://github.com/reactjs/react-redux "reactjs/react-redux: Official React bindings for Redux") を使用します。

2017年は Facebook 製の API 用のクエリ言語である [GraphQL](http://graphql.org "GraphQL | A query language for your API") が話題になりました。
Facebook はもちろん GitHub などの大企業が GraphQL を使っています。

GraphQL を使用したい場合は、GraphQL のデータを取得し、そのデータを React アプリケーションに効率的に渡せるようにする GraphQL クライアントフレームワークを使用することをお勧めします。それは、Facebook 製の [Relay](https://facebook.github.io/relay) もしくは [Apollo](https://www.apollographql.com) が該当します。

[こちらの記事](http://beautifulcode.1stdibs.com/2016/09/07/reconcile-relay-redux)に記載されている通り、Redux と Relay (もしくは Apollo) は相互に排他的である必要はありません。
それらを一緒に使用することで、Web 開発において非常に重要な関心の分離を提供することができます。
Redux はアプリケーションの State を保ち、アプリケーションがイベントにどのようにレスポンスするかを定義するのに役立ちます。Relay は GraphQL のデータの取得と更新ができます。

#### [MobX](https://mobx.js.org "Introduction | MobX")

MobX はシンプルでスケーラブルな State 管理ライブラリです。
Redux より覚える量が少なく記述するコードの量が少なくて済むため、最近注目を集めています。
そのため、Redux と比べると自由度が高いため大規模なアプリケーション開発にはあまり向いていません。

MobX に React をブリッジングする場合は、[mobx-react](https://github.com/mobxjs/mobx-react "mobxjs/mobx-react: React bindings for MobX") を使用します。

### HOC (Higher-Order Components)

HOC は、[高階関数](https://ja.wikipedia.org/wiki/%E9%AB%98%E9%9A%8E%E9%96%A2%E6%95%B0 "高階関数 - Wikipedia")ならぬ高階コンポーネントです。
つまり、コンポーネントを受け取って新しいコンポーネントを返す関数です。
コンポーネント間のクロスカットコンサーン (横断的関心事) を処理する [Mixin の代替](https://reactjs.org/blog/2016/07/13/mixins-considered-harmful.html "Mixins Considered Harmful - React Blog")として利用されていたりします。
コンポーネントロジックを抽象化し再利用したい時や SFC (Stateless Functional Components) にライフサイクルメソッドを追加したい時など有用です。

HOC は React API の一部ではなく、React の構成上の性質から生まれるパターンです。

```js
function higherOrderComponent(WrappedComponent) {
  return class extends React.Component {
    render() {
      return <WrappedComponent {...this.props}/>;
    }
  }
}

const EnhancedComponent = higherOrderComponent(WrappedComponent);
```

#### ~~[Recompose](https://github.com/acdlite/recompose "acdlite/recompose: A React utility belt for function components and higher-order components.")~~

> ## A Note from the Author (acdlite, Oct 25 2018):
>
> Hi! I created Recompose about three years ago. About a year after that, I joined the React team. Today, we announced a proposal for [*Hooks*](https://reactjs.org/hooks). Hooks solves all the problems I attempted to address with Recompose three years ago, and more on top of that. I will be discontinuing active maintenance of this package (excluding perhaps bugfixes or patches for compatibility with future React releases), and recommending that people use Hooks instead. **Your existing code with Recompose will still work**, just don't expect any new features. Thank you so, so much to [@wuct](https://github.com/wuct) and [@istarkov](https://github.com/istarkov) for their heroic work maintaining Recompose over the last few years.
>
> [acdlite/recompose: A React utility belt for function components and higher-order components.](https://github.com/acdlite/recompose/blob/master/README.md)

Recompose は、HOC のための React ユーティリティライブラリです。
React 用 Loadash ライクなライブラリと考えて問題ないようです。

例えば、リストを表示する `PostsList` という SFC にライフサイクルを追加したい場合は、以下のように記述します。

```jsx
const PostsList = ({ posts }) => (
  <ul>{posts.map(p => <li>{p.title}</li>)}</ul>
)

const PostsListWithData = lifecycle({
  componentDidMount() {
    fetchPosts().then(posts => {
      this.setState({ posts });
    })
  }
})(PostsList);
```

他にも、Props を加工したり、State や Handler を追加したりする便利な関数が用意されています。

### Routing

URL を変更してビューを切り替える必要がない場合は、条件付きレンダリングで十分です。
しかし、それは本当に小さい React アプリケーションにのみ当てはまる要件でしょう。
おそらくほとんどの開発者は React Router のようなルーティングライブラリが必要です。

#### [React Router](https://github.com/ReactTraining/react-router "ReactTraining/react-router: Declarative routing for React")

React Router は React 用のルーティングライブラリです。

React Router v4 から [react-router](https://github.com/ReactTraining/react-router/tree/master/packages/react-router) の代わりに以下のライブラリをインストールする必要があることに注意してください。これらをインストールすると、react-router は依存関係としてインストールされます。

| React Web アプリケーション | React Native アプリケーション |
| -------------------------- | ----------------------------- |
| [react-router-dom](https://github.com/ReactTraining/react-router/tree/master/packages/react-router-dom) | [react-router-native](https://github.com/ReactTraining/react-router/tree/master/packages/react-router-native) |

React Router を学びたい場合は[こちら](https://reacttraining.com/react-router "React Router: Declarative Routing for React.js")を参照してください。

### Testing

#### [Jest](http://facebook.github.io/jest/ja/ "Jest · ?快適なJavaScriptのテスト")

Jest は Facebook 製の JavaScript テストフレームワークです。
テストの環境はもちろん、テストの構造からアサーション機能、モック、スパイ、スタブなどのテストするための基本的な機能を全て提供しています。
[スナップショットテスト](https://facebook.github.io/jest/docs/ja/snapshot-testing.html "スナップショットテスト · Jest")やコードカバレッジレポートを生成することができます。

余談ですが、E2E テストツールといえばみんな大好き？ [Selenium](http://www.seleniumhq.org "Selenium - Web Browser Automation") ですよね。
[Trending repositories on GitHub](https://github.com/trending/javascript "Trending JavaScript repositories on GitHub today") に、[Selenium WebDriver](http://www.seleniumhq.org/projects/webdriver "Selenium WebDriver") に Jest テストをコネクトする [Jest WebDriver Integration](https://github.com/alexeyraspopov/jest-webdriver "alexeyraspopov/jest-webdriver: Connect Jest tests to Selenium WebDriver") なんていうのがランクインしていました。現在開発中らしいですが、完成が楽しみですね！

#### [Enzyme](http://airbnb.io/enzyme "Introduction · Enzyme")

Enzyme は Airbnb 製 の React コンポーネントをテストするためのユーティリティです。
Enzyme の API は、DOM 操作とトラバーサルのための jQuery の API を模倣することにより、直感的で柔軟性があります。
そのため、[React 公式でも推奨](https://reactjs.org/docs/test-utils.html#overview)しています。

低レベルな API で十分な場合は ReactTestUtils で十分ですが、より高レベルな API を使用したい場合は Enzyme の使用をお勧めします。

### Linter

Linter は静的コード解析ツールです。
JavaScript のコードスタイルを強制したり、エラーや潜在的な問題を検出することができます。

#### [ESLint](https://eslint.org "ESLint - Pluggable JavaScript linter")

ESLint は JavaScript Linter です。
類似ツールとして [JSLint](http://jslint.com "JSLint: The JavaScript Code Quality Tool") や [JSHint](http://jshint.com "JSHint, a JavaScript Code Quality Tool") があります。

現状、JavaScript Linter の中では [npmtrends](http://www.npmtrends.com/eslint-vs-jslint-vs-jshint) と [GitHub Star History](http://www.timqian.com/star-history/#eslint/eslint&douglascrockford/JSLint&jshint/jshint) を参照して分かる通りデファクトスタンダードです。

ESLint の [Shareable Config](http://eslint.org/docs/developer-guide/shareable-configs) である [eslint-config-airbnb](https://github.com/airbnb/javascript/tree/master/packages/eslint-config-airbnb "https://github.com/airbnb/javascript/tree/master/packages/eslint-config-airbnb") を利用することで [Airbnb の JavaScript スタイルガイド](https://github.com/airbnb/javascript "airbnb/javascript: JavaScript Style Guide")のルールに則っているか解析できます。
Shareable Config は[こちら](https://www.npmjs.com/browse/keyword/eslint-config)から選択することができます。

#### [stylelint](https://stylelint.io "stylelint")

stylelint は ESLint ライクな CSS Linter です。言うなれば、CSS 版 ESLint です。
類似ツールとして [CSSLint](http://csslint.net "CSS Lint") や [CSScomb](http://csscomb.com "CSScomb: Makes your code beautiful") があります。

現状、CSS Linter の中では [npmtrends](http://www.npmtrends.com/stylelint-vs-csslint-vs-csscomb) と [GitHub Star History](http://www.timqian.com/star-history/#stylelint/stylelint&CSSLint/csslint&csscomb/csscomb.js) を参照して分かる通りデファクトスタンダードです。

ESLint 同様、stylelint でも Shareable Config を利用することができます。
Shareable Config は[こちら](https://www.npmjs.com/browse/keyword/stylelint-config)から選択することができます。

CSS Modules 及び Styled Components でも利用することができます。

### Code Formatter

#### [Prettier](https://prettier.io "Prettier · Opinionated Code Formatter")

Prettier は JavaScript や JSX を始めとした様々な言語の Code Formatter です。
[prettier-eslint](https://github.com/prettier/prettier-eslint "prettier/prettier-eslint: Code prettier eslint --fix Formatted Code") を利用することで ESLint と連携することもできます。

以下は、Prettier によるコードのフォーマット前後の結果です。

**Before:**

```js
foo(reallyLongArg(), omgSoManyParameters(), IShouldRefactorThis(), isThereSeriouslyAnotherOne());
```

**After:**

```js
foo(
  reallyLongArg(),
  omgSoManyParameters(),
  IShouldRefactorThis(),
  isThereSeriouslyAnotherOne()
);
```

### Dev Tools

#### [React Developer Tools](https://github.com/facebook/react-devtools "facebook/react-devtools: An extension that allows inspection of React component hierarchy in the Chrome and Firefox Developer Tools.")

![React Developer Tools](https://github.com/facebook/react-devtools/blob/master/images/devtools-full.gif?raw=true)

React Developer Tools は、コンポーネントの Props や State を含む React コンポーネントの階層をインスペクトするためのツールです。
[Chrome extension](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi) や [Firefox extension](https://addons.mozilla.org/firefox/addon/react-devtools/)、[Standalone app (Safari, React Native, etc)](https://github.com/facebook/react-devtools/blob/master/packages/react-devtools/README.md) にも対応しています。

#### [React Performance Devtool](https://github.com/nitin42/react-perf-devtool "nitin42/react-perf-devtool: A browser developer tool extension to inspect performance of React components.")

![React Performance Devtool](https://camo.githubusercontent.com/06e8e77abf033532cc85af1886e9bda870893c75/687474703a2f2f672e7265636f726469742e636f2f6d3859763152545236762e676966)

React Performance Devtool は、Reactコンポーネントのパフォーマンスをインスペクトするためのツールです。
使用されていないコンポーネントを確認したり、どのコンポーネントの読み込みに時間がかかるか調べたりすることができます。
[Chrome extension](https://chrome.google.com/webstore/detail/react-performance-devtool/fcombecpigkkfcbfaeikoeegkmkjfbfm) や [Firefox extension](https://addons.mozilla.org/en-US/firefox/addon/nitin-tulswani/) に対応しています。Standalone app については近日公開予定です。

### UI Components

ボタンや、テキストボックス、テーブル、Date ピッカーなどの UI コンポーネントを一から実装したくない開発者向けに、既に[数多くの UI コンポーネント](https://reactjs.org/community/ui-components.html "UI Components - React") が存在しています。
そのため、お好きな UI コンポーネントを選択すべきだと思いますが、あえて挙げるとするなら、Semantic UI と Material-UI、OnsenUI でしょうか。

#### [Semantic UI](https://semantic-ui.com "Material UI")

Semantic UI はテーマに合わせてデザインされた UI コンポーネントフレームワークです。

#### [Material-UI](http://www.material-ui.com "Material-UI")

Material-UI は、[Google が提唱する Material デザイン](https://material.io "Material Design")な UI コンポーネントフレームワークです。

#### [OnsenUI](https://github.com/OnsenUI/OnsenUI "OnsenUI/OnsenUI: Mobile app development framework and SDK using HTML5 and JavaScript. Create beautiful and performant cross-platform mobile apps. Based on Web Components, and provides bindings for Angular 1, 2, React and Vue.js.")

![OnsenUI](https://camo.githubusercontent.com/7645060259afb4904e589e5ad9e0cbb94182859f/68747470733a2f2f6f6e73656e75692e6769746875622e696f2f6172742f73686f77636173652f73686f77636173652d6f6e73656e75692e676966)

Onsen UI は、Javascript を使用して Android と iOS の両方で美しいハイブリッドとモバイルの Web アプリケーションを作成するのに役立つ UI コンポーネントライブラリです。

[Onsen UIとは？](https://ja.onsen.io/v2/guide/#onsen-uitoha "Onsen UIをはじめよう - Onsen UI")

> Onsen UIは、下のような特徴を持つライブラリです。
>
> * モバイルアプリの開発に特化したUIコンポーネントの集まりです。
> * ネイティブなiOSとAndroidのデザインガイドに準拠したデザインと機能を持っています。
> * 無料で利用でき、完全にオープンソースなソフトウェアです（[Apache v2 license](https://github.com/OnsenUI/OnsenUI/blob/master/LICENSE)）。
>
> Onsen UIを使うと、モバイルWebアプリの上でネイティブUIと同等のUX（ユーザー・エクスペリエンス）を提供することができます。モバイルWebアプリ（[Progressive Web Apps](https://developers.google.com/web/progressive-web-apps)とも呼ばれます）や、Cordovaを用いたハイブリッドアプリ開発に最適です。

筆者は業務で [Cordova](https://cordova.apache.org "Apache Cordova") を利用したネイティブアプリケーション開発を行っているということもあり、今年最も利用したい UI コンポーネントです。

[React Native](https://facebook.github.io/react-native "React Native · A framework for building native apps using React") にも [NativeBase](https://nativebase.io "NativeBase | Essential cross-platform UI components for React Native") というハイブリッド UI コンポーネントがあります。

### Components Workbenches

#### [Storybook](https://storybook.js.org "Storybook - UI dev environment you'll love to use")

![Storybook](https://github.com/storybooks/storybook/blob/master/app/react/docs/demo.gif?raw=true)

Storybook は、UI コンポーネントを定義、開発、およびテストするための開発環境です。
類似ツールと比較すると圧倒的な人気です。
この人気の裏には、React 以外にも React Native や Vue、 Angular もサポートや、コンポーネントの設計、ドキュメンテーション、テスト、インタラクティブ機能などのための多くの [Addons](https://storybook.js.org/addons/introduction) の存在があります。

以下のように、JavaScript で UI コンポーネントを定義します。

```js
import React from 'react'
import { storiesOf } from '@storybook/react'
import { action } from '@storybook/addon-actions'
import Button from '../components/Button'

storiesOf('Button', module)
  .add('default', () => (
    <Button onClick={action('clicked')}>Push Me</Button>
  ))
  .add('large size', () => <Button size="large">Push Me</Button>)
```

[よく比較される](https://spectrum.chat/thread/d6c4e134-85ec-42be-80d2-a4ef3069ed3d)類似ツールとして、[Styleguidist](https://react-styleguidist.js.org "React Styleguidist: isolated React component development environment with a living style guide") があります。

![Styleguidist](https://camo.githubusercontent.com/7af8e5fc43288807978f28530656275008c5afbf/68747470733a2f2f64337676366c703535716a6171632e636c6f756466726f6e742e6e65742f6974656d732f32373142333732783130325330633035326933462f72656163742d7374796c6567756964697374372e676966)

公式ドキュメントに 「[React Styleguidist と Storybook との違い](https://react-styleguidist.js.org/docs/cookbook.html#whats-the-difference-between-styleguidist-and-storybook)」 が記載されています。
**ここに記載されている比較表には騙されないで下さい。
Styleguidist と Addons 無しの Storybook との比較です。**
Storybook より Styleguidist があたかも優れているように見えますが Addons を利用することで、No の項目のほとんどが Yes になります。

Storybook との大きな違いは、Styleguidist は以下のように Markdown で UI コンポーネントを定義することでしょう。

~~~md
React button component example:

```js　
<Button onClick={() => console.log('clicked')>Push Me</Button>
```　

Large size:

```js　
<Button size="large">Push Me</Button>
```　
~~~

Styleguidist は、ソースコードの JSDoc コメントブロックや PropTypes の宣言を [react-docgen](https://github.com/reactjs/react-docgen) を解析してドキュメントに自動反映させるため、スタイルガイドの作成という面から見れば強力です。
しかし、Storybook はコンポーネントを開発するための Addons が豊富に用意されているため、UI コンポーネントの開発環境という面から見れば強力です。

また、類似ツールとして [Bluekit](http://bluekit.blueberry.io "React BlueKit | by Blueberry") や [Catalog](http://www.catalog.style "Catalog") なども存在します。
Netflix のエンジニアリングチームが Storybook の代替案として Bluekit を採用して使用しているらしいです。

それぞれのツールの比較は「[React Components Living Style Guides Overview | nearForm](https://www.nearform.com/blog/react-living-style-guides "React Components Living Style Guides Overview | nearForm")」を参照して下さい。
若干情報が古いため、改善されているデメリット (CONS) の項目があります。

#### [React Studio](https://reactstudio.com "React Studio")

React Studio は GUI で設計したコンポーネントを React コンポーネントに変換することができるツールです。
詳しくは、少し前に話題になった[こちらの記事](https://qiita.com/yuxio/items/3cb07d946e22ed1b5fc5 "ドラッグ&ドロップでReact製のWEBアプリがつくれるReactStudioがやばい - Qiita")を参照してください。

夢のようなツールですが、実際に触ったことがないため実務で利用できるかは疑問です。
Styled Components や UI Components などに対応しているのでしょうか？
時間があれば触ってみたいと思います。


## Redux

もっと多くの Redux のエコシステム以外も知りたい方は[こちら](https://redux.js.org/docs/introduction/Ecosystem.html "Ecosystem · Redux")を参照してください。

### Utilities

#### [Reselect](https://github.com/reactjs/reselect "reactjs/reselect: Selector library for Redux")

Reselect は React Community によって作られたシンプルな Selector ライブラリです。
不要な再レンダリングや再計算を防ぎ、パフォーマンスを向上させることができます。

Redux Store の State を計算 (フィルタリングなど) して Props としてコンポーネントに渡す際、以下のように `mapStateToProps` 関数を利用すると思います。

```jsx
// 計算
const getFilteredList = (list, filter) => {
  // filter の値に応じて list をフィルタリングして返す
}

const mapStateToProps = (state) => {
  return {
    list: getFilteredList(state.list, state.filter)
  }
}
```

この時、State ツリー ( `state` ) で変更が発生した場合、計算で使用しない無関係な部分 (`state.list` と `state.filter` 以外) の変更でも再計算されてしまいます。
Reselect を使用すると、State ツリーの関係ある部分 (`state.list` と `state.filter`) に変更が加わった時だけ再計算できます。
これにより、パフォーマンス上の問題を解決することができます。

詳しくは、[こちらの記事](https://qiita.com/zaki-yama/items/5258e6f1ae37f63034b9 "Reduxのreselectとは - Qiita")を参照してください。

#### [Nomalizr](https://github.com/paularmstrong/normalizr "paularmstrong/normalizr: Normalizes nested JSON according to a schema")

多くの API は頻繁に深くネストされた JSON オブジェクトをレスポンスします。
Normalizr はスキーマのタイプとリレーションを定義し、スキーマとレスポンスデータを渡すことで正規化されたデータを出力できます。
その出力を Action に含め、ストアの更新に使用することで State をフラットに保つことができます。

正規化することで、以下のような[懸念事項](https://redux.js.org/docs/recipes/reducers/NormalizingStateShape.html)を解決することができます。

> * データがいくつかの場所で複製されると、適切に更新されることを確認するのがより困難になります。
> * ネストされたデータは、対応する Reducer ロジックがよりネストされることでより複雑にする必要があることを意味します。特に、深くネストされたフィールドを更新しようとすると、非常に醜いものになります。
> * イミュータブルデータ更新では、State ツリー内のすべての祖先をコピーして更新する必要があり、新しいオブジェクト参照によって接続された UI コンポーネントが再レンダリングされるため、深くネストされたデータオブジェクトを更新すると、表示されているデータが実際には変更されていない場合でも再レンダリングされます。

以下は、Nomalizr を使用してブログ記事のデータを正規化するサンプルです。

以下は、正規化するための `originalData` です。

```js
{
  "id": "123",
  "author": {
    "id": "1",
    "name": "Paul"
  },
  "title": "My awesome blog post",
  "comments": [
    {
      "id": "324",
      "commenter": {
        "id": "2",
        "name": "Nicole"
      }
    }
  ]
}
```

`article` というエンティティタイプと、それにネストされた `users` と `comments` という2つのエンティティタイプを持っています。
`schema` オブジェクトを使用してスキーマを定義し、`nomalize` 関数を使用することで3つのエンティティタイプを全て正規化できます。

```js
import { normalize, schema } from 'normalizr';

// users スキーマを定義
const user = new schema.Entity('users');

// comments スキーマを定義
const comment = new schema.Entity('comments', {
  commenter: user
});

// article スキーマを定義
const article = new schema.Entity('articles', {
  author: user,
  comments: [ comment ]
});

const normalizedData = normalize(originalData, article);
```

`normalizedData` は以下のようになります。

```js
{
  result: "123",
  entities: {
    "articles": {
      "123": {
        id: "123",
        author: "1",
        title: "My awesome blog post",
        comments: [ "324" ]
      }
    },
    "users": {
      "1": { "id": "1", "name": "Paul" },
      "2": { "id": "2", "name": "Nicole" }
    },
    "comments": {
      "324": { id: "324", "commenter": "2" }
    }
  }
}
```

`denormalize` 関数を使用することで正規化されたデータを非正規化することができます。
正規化されたデータ (State) はコンポーネントで扱いづらいため、非正規化することをお勧めします。
正規化されたデータを大量にネストされたオブジェクトに戻すことで、アプリケーションのパフォーマンスが低下する恐れがあることにご注意ください。

#### [Immutable.js](https://facebook.github.io/immutable-js "Immutable.js")

Immutable.js は、Facebook 製のイミュータブル (不変) なデータ構造を扱うためのライブラリです。

[Immutable.js を選択する必要性](https://redux.js.org/docs/recipes/UsingImmutableJS.html#why-should-i-choose-immutablejs-as-an-immutable-library "Using Immutable.JS with Redux · Redux") として以下の項目が挙げられます。

* 不変性を保証
* 豊富な API
* パフォーマンス

React で不変性を扱うことの長所と短所について知りたい方は、[こちら](http://reactkungfu.com/2015/08/pros-and-cons-of-using-immutability-with-react-js/)を参照してください。

### Actions

#### [redux-actions](https://redux-actions.js.org "Read Me · redux-actions")

redux-actions は [Flux Standard Action](https://github.com/acdlite/flux-standard-action "acdlite/flux-standard-action: A human-friendly standard for Flux action objects.") のユーティリティです。

Flux Action オブジェクトの構造をどうするかは開発者に委ねられます。
この自由な構造に対してヒューマンフレンドリーな標準規約を設けたものが FSA (Flux Standard Action) になります。

FSA は以下のような構造となっています。

**Basic:**

```js
{
  type: 'ADD_TODO',
  payload: {
    text: 'Do something.'
  }
}
```

**Error:**

```js
{
  type: 'ADD_TODO',
  payload: new Error(),
  error: true
}
```

FSA のユーティリティ関数として、Action が FSA に準拠しているか確認する `isFSA(action)` と、Action がエラーか確認する `isError(action)` があります。
筆者は主に ActionCreator のテストコードでこれらの関数を使用しています。

```js
import { isFSA, isError } from 'flux-standard-action';
```

redux-actions はこの FSA に準拠するためのユーティリティです。
これにより、プロジェクト内で Action の構造を統一することができます。

redux-actions は以下のように ActionCreator や Reducer を作成することができます。

```js
import { createActions, handleActions, combineActions } from 'redux-actions'

const defaultState = { counter: 10 };

const { increment, decrement } = createActions({
  INCREMENT: amount => ({ amount }),
  DECREMENT: amount => ({ amount: -amount })
});

const reducer = handleActions({
  [combineActions(increment, decrement)](state, { payload: { amount } }) {
    return { ...state, counter: state.counter + amount };
  }
}, defaultState);

export default reducer;
```

### Middleware

#### Async Actions

##### [Redux Thunk](https://github.com/gaearon/redux-thunk "gaearon/redux-thunk: Thunk middleware for Redux")

Redux Thunk は Action ではなく 関数を返す非同期な Action Creator を記述することができるようにする Redux ミドルウェアです。

以下のように、非同期な Dispatch を実行する関数を返す ActionCreator を記述できます。

```js
function fetchData(someValue) {
  return (dispatch, getState) => {
    dispatch({type : "REQUEST_STARTED"});

    myAjaxLib.post("/someEndpoint", {data : someValue})
      .then(response => dispatch({type : "REQUEST_SUCCEEDED", payload : response})
      .catch(error => dispatch({type : "REQUEST_FAILED", error : error});
  };
}

function addTodosIfAllowed(todoText) {
  return (dispatch, getState) => {
    const state = getState();

    if(state.todos.length < MAX_TODOS) {
      dispatch({type : "ADD_TODO", text : todoText});
    }
  }
}
```

##### [redux-saga](https://github.com/redux-saga/redux-saga "redux-saga/redux-saga: An alternative side effect model for Redux apps")

[redux-saga/README_ja.md at master · redux-saga/redux-saga](https://github.com/redux-saga/redux-saga/blob/master/README_ja.md "redux-saga/README_ja.md at master · redux-saga/redux-saga")

> `redux-saga` は React/Redux アプリケーションにおける副作用（データ通信などの非同期処理、ブラウザキャッシュへのアクセスのようなピュアではない処理）をより簡単で優れたものにするためのライブラリです。

> Saga はアプリケーションの中で副作用を個別に実行する独立したスレッドのような動作イメージです。 redux-saga は Redux ミドルウェアとして実装されているため、スレッドはメインアプリケーションからのアクションに応じて起動、一時停止、中断が可能で、Redux アプリケーションのステート全体にアクセスでき、Redux アクションをディスパッチすることもできます。

以下のように、ジェネレーター関数を使用して非同期処理を同期的に記述できます。

```js
function* fetchData(action) {
  const {someValue} = action;
  try {
    const result = yield call(myAjaxLib.post, "/someEndpoint", {data : someValue});
    yield put({type : "REQUEST_SUCCEEDED", payload : response});
  }
  catch(error) {
    yield put({type : "REQUEST_FAILED", error : error});
  }
}

function* addTodosIfAllowed(action) {
  const {todoText} = action;
  const todos = yield select(state => state.todos);

  if(todos.length < MAX_TODOS) {
    yield put({type : "ADD_TODO", text : todoText});
  }
}
```

詳しくは、[こちらの記事](https://qiita.com/kuy/items/716affc808ebb3e1e8ac "redux-sagaで非同期処理と戦う - Qiita")を参照してください。

### Routing

#### [react-router-redux](https://github.com/ReactTraining/react-router/tree/master/packages/react-router-redux "react-router/packages/react-router-redux at master · ReactTraining/react-router")

react-router-redux は Reat Router と Redux の同期を保つライブラリです。URL と State を同期することができます。
Redux DevTools などのタイムトラベル機能を使用して、Action の記録、永続化、および再生に注意を払う場合に便利です。

### Forms

#### [Redux Form](https://redux-form.com "Redux Form - Redux Form")

Redux Form は Redux で Form の State を管理できるように実装する機能を提供するライブラリです。
Form のバリデーションも簡単に実装できます。

### Dev Tools

#### [Redux DevTools](https://github.com/gaearon/redux-devtools "gaearon/redux-devtools: DevTools for Redux with hot reloading, action replay, and customizable UI")

![Redux DevTools](https://camo.githubusercontent.com/a0d66cf145fe35cbe5fb341494b04f277d5d85dd/687474703a2f2f692e696d6775722e636f6d2f4a34476557304d2e676966)

Redux DevTools は、タイムトラベル UI の付いた Action ロガーです。
Action ペイロード及び State のロギングとそれらの確認ができます。
Reducer のためのホットリロード機能とエラーハンドリング機能があります。

以下のような Redux DevTools の Monitor を組み合わせることで、デバッグ環境を拡張することができます。

| DevTools Monitors | Overview |
| ----------------- | -------- |
| [Log Monitor](https://github.com/gaearon/redux-devtools-log-monitor) | ツリー状の表示ができるデフォルトモニター。 |
| [Dock Monitor](https://github.com/gaearon/redux-devtools-dock-monitor) | モニターのための、サイズ変更と移動が可能な Dock。 |
| [Slider Monitor](https://github.com/calesce/redux-slider-monitor) | 記録された Action を再生するカスタムモニター。 |
| [Inspector](https://github.com/alexkuz/redux-devtools-inspector) | Action のフィルタリング、差分の調査、深くネストされた状態の変更監視のために状態のパスをピン留めしたりできるカスタムモニター。 |
| [Diff Monitor](https://github.com/whetstone/redux-devtools-diff-monitor) | Action 間での Store の差分が取れるモニター。 |
| [Filterable Log Monitor](https://github.com/bvaughn/redux-devtools-filterable-log-monitor/) | Action 間での Store の差分が取れるモニター。 |
| [Chart Monitor](https://github.com/romseguy/redux-devtools-chart-monitor) | チャート表示ができるモニター。 |
| [Filter Actions](https://github.com/zalmoxisus/redux-devtools-filter-actions) | Action をフィルタリングでき、他のモニターを内包できるモニター。 |

#### [Redux DevTools Extension](https://github.com/zalmoxisus/redux-devtools-extension "zalmoxisus/redux-devtools-extension: Redux DevTools extension.")

![Redux DevTools Extension](https://cloud.githubusercontent.com/assets/7957859/18002950/aacb82fc-6b93-11e6-9ae9-609862c18302.png)

Redux DevTools Extension は、Redux デバッグ機能を提供するブラウザーエクステンションです。

Redux DevTools をアプリに統合したくない場合はこのエクステンションをお勧めします。

[Chrome extension](https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd) や [Firefox extension](https://addons.mozilla.org/en-US/firefox/addon/remotedev/) に対応しています。その他ブラウザーについては [Remote Redux DevTools](https://github.com/zalmoxisus/remote-redux-devtools "zalmoxisus/remote-redux-devtools: Redux DevTools remotely.") を使用することで対応することができます。

## まとめ

エコシステムの選択に限った話ではありませんが、おそらくベターやベストあっても正解はありません。
プロジェクトの要件やニーズ、開発者のスキルや学習コストに応じて適切なエコシステムを選択し、良い React ライフをお送りください！