console.lealog();

@leader22のWeb系に関する勉強めもブログですのだ

React Today and Tomorrow and 90% Cleaner React の要点まとめ

React HooksにはじまりAlgebraic EffectsだFPだなんだと話題に事欠かない昨今ですが、そういうのは根本から見ていくに限る!ということで。

ReactConf2018のHooksが発表されたセッションを見ながら書いたメモです。

React Today and Tomorrow and 90% Cleaner React - YouTube

1時間半もあるんやでこの動画・・。
まあ実際は3人のスピーカーが交代で話してるので、3部作だったりする。

React Today

Reactの歩み

  • `npm i`される回数は年々70%もUPしてる
  • 採用企業も増えた
  • Google TrendsではついにjQueryを抜いた

Reactの使命

  • よりよいUIを簡単に作れるようにすること
  • そのために大事なこと3つ
  • 1. 複雑な要件を単純化できること
    • Suspenseはその好例
  • 2. パフォーマンスに優れている
  • 3. Devtoolsが手厚い
    • Profilerがついてる

Reactの課題

  • 1. 共通コードの取り回し問題
  • 現時点での解法としてよく見るのはこの2つ
    • HoC
    • Render props
  • ただしWrapper hellに陥りがち
    • = HoCがめちゃくちゃネストすること
  • 2. コンポーネントの肥大化問題
    • 主にLifecycleフックが膨れがち
    • 非同期処理とか、DOMさわったりとか
  • 3. classコンポーネントの扱い難しい問題
    • どのコンポーネントをいつ使えばいいのどう書けばいいの問題
    • 人間には早すぎた
    • マシーンにも優しくない(HMRとか実装大変らしい)

React Tommorow

課題にどう立ち向かうか

RFC
  • Reactに新機能を追加するときは、まずRFCを用意するようにした
  • いきなり機能追加するのではなく、Proposalとして出す
    • なぜこの機能が必要か
    • どういう経緯か
  • コミュニティからのフィードバックを反映していく

(どういう機能を追加しようとしてるかのデモ)

import React from 'react';

export default class Greeting extends React.Component {
  constructor(props) {
    super(props);
    this.state = { name: 'Mary' };
    this.onChangeName = this.onChangeName.bind(this);
  }

  onChangeName(ev) {
    this.setState({ name: ev.target.value });
  }

  render() {
    return (
      <section>
        <input
          value={this.state.name}
          onChange={this.onChangeName}
        />
      </section>
    );
  }
}
  • これを、Functionalコンポーネントでやりたい
  • Hooksと呼んでる仕組みで解決すると、こう書ける
import React, { useState } from 'react';

export default function Greeting(props) {
  const [name, setName] = useState('Mary');

  function onChangeName(ev) {
    setName(ev.target.value);
  }

  return (
    <section>
      <input
        value={this.state.name}
        onChange={this.onChangeName}
      />
    </section>
  );
}
  • この2つの例の違い
  • classコンポーネントの場合
    • `this`によるアクセスが発生
    • `state`はオブジェクト
    • `handler`も別途定義が必要
  • Hooksを使う場合
    • `this`は存在しない
    • `state`と`handler`は都度用意する
    • `state`と`handler`はペアになってる

Hooks

  • 何がしたいのかがわかりやすい
    • あれこれやっちゃう関数みたいなのは作れない
    • `state`なら`state`のことだけやる
    • Lifecycleフックの中でごちゃごちゃもできない
  • Hooksは呼び出し順に依存する
  • なので`if`の中に書いたりはできない
    • Linterで検知できる
  • Hooksは他にも種類がいくつかある
`useContext()`
  • Context APIを使える
  • Render propsではなくダイレクトに変数にできる
  • つまりネストが減る
`useEffect()`
  • Lifecycleフックの代わりになる
    • 中でReactが用意してないことをする
  • そのコンポーネントのスコープの内容を使って何かする
  • 複数のことをやりたい場合は複数のHooksにする
    • 役割を持たせすぎないことを推奨
  • 関数を返すと、それが`componentWillUnmount()`の代わりになる
チューニング
  • この調子でHooksを増やしていくと、コードは肥大化する
  • しかし幸いなことにこれらはすべてただの関数!
  • 切り出して使うことができる
    • `useXxx()`として切り出すのを推奨
    • CustomHooksと呼んでる
    • もちろん引数も渡せる

Hooksまとめ

  • classコンポーネントでなくとも同等のことができる
  • 共通コードは関数にしてしまえる
  • 使うか使わないかも自由
    • 無理してまでコードを書き換えたりしないで
    • 今までと異なるマインドセットが必要なので、最初は大変だと思う
  • まだProposalではなるが、これからのReactになっていくもの
Reactのロゴ
  • そういえば、なぜ原子(Atom?)?
  • 組み合わさってはじめて具体化するもの
  • Hooksも組み合わせによりコンポーネントを成す
    • Hooksを通して、Reactの真髄に触れるイメージ

90% Cleaner React

Hooksを使ってリファクタ

  • Render propsによるWrapper hellなコードを書き換え
    • class w/ MediaQueriesなコードもHooksできれいに
    • `useEffect()`の第2引数で、`componentDidUpdate()`をカバー
  • より実践的な例として、カルーセルのコードを書き換え
    • `useState()`がいっぱいでてきたらどうする?
    • `useReducer()`があるよ
    • Refには`useRef()`があるよ
  • まだ全てのユースケースを把握できてるわけではない
    • フィードバック待ってます

ライブコーディングなので動画見たほうが早いですね・・!