React HooksにはじまりAlgebraic EffectsだFPだなんだと話題に事欠かない昨今ですが、そういうのは根本から見ていくに限る!ということで。
ReactConf2018のHooksが発表されたセッションを見ながら書いたメモです。
1時間半もあるんやでこの動画・・。
まあ実際は3人のスピーカーが交代で話してるので、3部作だったりする。
React Today
Reactの歩み
- `npm i`される回数は年々70%もUPしてる
- 採用企業も増えた
- Google TrendsではついにjQueryを抜いた
Reactの使命
- よりよいUIを簡単に作れるようにすること
- そのために大事なこと3つ
- 1. 複雑な要件を単純化できること
- Suspenseはその好例
- 2. パフォーマンスに優れている
- Code splittingとかにも優しい
- Time Slicingなどレンダリングにも効く
- 3. Devtoolsが手厚い
- Profilerがついてる
Reactの課題
- 1. 共通コードの取り回し問題
- 現時点での解法としてよく見るのはこの2つ
- HoC
- Render props
- ただしWrapper hellに陥りがち
- = HoCがめちゃくちゃネストすること
- 2. コンポーネントの肥大化問題
- 主にLifecycleフックが膨れがち
- 非同期処理とか、DOMさわったりとか
- 3. classコンポーネントの扱い難しい問題
- どのコンポーネントをいつ使えばいいのどう書けばいいの問題
- 人間には早すぎた
- マシーンにも優しくない(HMRとか実装大変らしい)
React Tommorow
課題にどう立ち向かうか
- 1つずつ解決することはできる
- ただし1つが解決すると、もう1つが悪化することもある
- どうしよう?
- ReactがclassコンポーネントよりシンプルなAPIを持ってないのが問題
- Mixinっていう概念が昔あった
- でも失敗だった
- https://reactjs.org/blog/2016/07/13/mixins-considered-harmful.html
- 新しいナニカが必要
RFC
- Reactに新機能を追加するときは、まずRFCを用意するようにした
- いきなり機能追加するのではなく、Proposalとして出す
- なぜこの機能が必要か
- どういう経緯か
- コミュニティからのフィードバックを反映していく
(どういう機能を追加しようとしてるかのデモ)
- FunctionalコンポーネントでStateを持つにはどう書けばいい?
- 現状だとできなくて、classコンポーネントを使うしかない
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コンポーネントでなくとも同等のことができる
- 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()`があるよ
- まだ全てのユースケースを把握できてるわけではない
- フィードバック待ってます
ライブコーディングなので動画見たほうが早いですね・・!