React Native で React Hooks を使う
この記事は Farmnote Advent Calendar 2018 の 4 日目の記事です。
前回はエンジニアと自己紹介しておきながらエモい記事を書いたのでエンジニアらしく技術の話題です。今年の ReactConf で発表された React Hooks を React Native でも使ってみよう、という記事になります。
React Hooks とは
React Hooks の概要については公式のドキュメントが詳しいです。
https://reactjs.org/docs/hooks-intro.html
React.js を用いた開発では SFC という形で関数でコンポーネントを定義する潮流となってきた昨今、 state や Lifecycle methods を使いたいときに class で定義することが割と面倒になってきました。ここで面倒と言っているのは可読性やメンテナンス性も含めてのハナシです。
React Hooks は非常に乱暴にまとめると関数で定義したコンポーネントに state や各 Lifecycle における挙動を注入する仕組みです。わかる方向けには recompose で実現していたことを公式がよりメンテナンス性を高めて対応した、と言えばよいでしょうか。
イメージがつかない方は Dan Abramov が十八番とも言えるライブコーディングをしている動画がありますのでぜひ見てみてください。英語ですが Dan は非常にわかりやすく噛み砕いて説明しているので音声つきのほうが理解が進むと思います。
React Native で React Hooks を有効化する
React Hooks は現在 alpha version です。そのため React Native はおろか React.js でもインストールするだけでは使えないのですが、 Facebook の方が有効化する方法を記載してくださっています。
https://github.com/facebook/react-native/issues/21967#issuecomment-434113687
この手順を実施して作った repository がこちらです。
https://github.com/januswel/rn-hooks
直下に Renderer というディレクトリーがありますが、ここに記載されている手順でビルドした結果のファイル群を置いています。
そしてこれらを指示通りの場所にコピーするコマンドを npm scripts の postinstall として定義することで、 npm install するだけで使えるようにしている、という塩梅です。
Copy the contents of this directory, to your project's node_modules/react-native/Libraries/Renderer directory.
// snip
"postinstall": "cp -rf ./Renderer/* ./node_modules/react-native/Libraries/Renderer/",
// snip
state を注入してみる
state の代表例と言えば Controlled Components です。ということでまずは旧来の書き方で書いてみましょう。
// ControlledComponentClass.js
import React from 'react'
import { TextInput } from 'react-native'
export default class extends React.Component {
constructor(props) {
super(props)
this.state = {
value
}
this.handleChange = this.handleChange.bind(this)
}
handleChange(newValue) {
this.setState({
value: newValue,
})
}
render() {
return (
<TextInput
value={value}
onChangeText={handleChange}
/>
)
}
}
実際には style 指定などが入るのでもうちょっとごちゃごちゃしますが、本質的なところはこれですべてです。
ではまったく同じものを React Hooks を用いて書いてみましょう。そのものずばり、 useState を使います。
// ControlledComponentHooks.js
import React, { useState } from 'react'
import { TextInput } from 'react-native'
export default () => {
const [value, setValue] = useState('')
const handleChange = newValue => {
setValue(newValue)
}
return (
<TextInput
value={value}
onChangeText={handleChange}
/>
)
}
はい、これだけです。大体半分強といったところでしょうか、ひとめで収まるサイズになっていますね。メンテナンスしやすそうです。
Dan の動画でやっていたことなので動画を先に見た方は「知ってる」となる内容ですが、ひとめで利点がわかりやすいように文字起こししてみました。また、実際に写経してみると考えるよりとても楽だったことも発見です。本リリースが待ち遠しいですね。
ちなみにこれは関数で定義されているものの state を持ったコンポーネントなので SFC: Stateless Functional Components と呼ぶのはふさわしくない。ということで仲間内では単純に FC: Functional Components と呼んでいたりします。 16bit から 8bit になってしまいましたが単純な方がいいんです。
React Hooks で提供されているその他の関数について
先ほどあげた repository にその他の関数、 useContext や useEffect を使った実装がありますのでぜひ参考にしてみてください。
https://github.com/januswel/rn-hooks/blob/master/src/App.js
といってもこれも Dan の動画にそって自分で手を動かしてみたものなのですが。写経大事。
production 投入する ?
さて本題。
We know that React developers are focused on shipping products and don’t have time to look into every new API that’s being released. Hooks are very new, and it might be better to wait for more examples and tutorials before considering learning or adopting them.
( 超訳 ) React 開発者はプロダクトをリリースすることに関心があり、すべての API に目を通している時間がないことはわかっています。 React Hooks は成熟していないので、プロダクション投入する前にサンプルやチュートリアルが揃うのを待つのも手です。
とあるので、何も考えずに従おうというお気持ちです。 FC で書いていくのはメンテナンス性も含めて非常に魅力的なのですがまだ API が変わる可能性のあるものを投入するわけにはいきません。
コンポーネント単位でリファクタリングも可能なのが React.js の良いところなのでこの勧告は素直に受け取ったほうが良いでしょう。 React Hooks が本リリースを迎えた後に、長く保守するプロダクトであればリファクタリング、新規開発であれば最初から React Hooks で書く、でよいと考えています。それまでは個人で触りながらフィードバックできそうなところはフィードバックしてね、というのが Facebook が望んでいることのようですので。
まとめ
React Hooks が待ちきれない。
この記事が気に入ったらサポートをしてみませんか?