React Nativeに触れる機会が多くなって、フック(英語:hooks)という言葉にぶつかりました。hookを和訳すると、動詞の場合は、釘にかける、やホックで留める、ひっかける、など掛ける・留めるという意味です。名詞として使えば、かぎ・留め金・ホックですね。ただ、ReactやReact NativeにおけるいわゆるReact Hooksの場合、ちょっとこの意味をいったん忘れてしまった方が、すんなり理解できるようになるかもしれません。
React Hooks(フック)とは何か
フックはReact バージョン 16.8.0 から採用された新機能になります。
state(*1) などの React の機能を、クラス(class)を書かずに使えるようになったり関数内部で使用が可能になります。
(*1 sateと聞いてデザインパターンと関連付けられる方はさすがだと思います。コンポーネントの状態をつかさどるのでほぼほぼ同義だと考えても良いかもです。)
React、React Nativeにおけるhooksは代表的な2つの仕組みがあります。
stateフック(ステートフック)とeffectフック(副作用フック)ですね。それそれについては後述します。
では、実際どんなコードがフックを使ってソースを簡略化したり、可読性を向上させられるのか見てみましょう。
React Hooksを利用すると何が便利なのか。
ステータスフック編
React Hooks前とReact Hooks後でどのように異なるのか比較してみましょう。次のコードはReact Hooks前のソースコードです。
import React from 'react';
class ExComponet extends React.Component {
constructor(props) {
super(propds);
this.state = { feeling: '' };
this.handleChange = this.changer.bind(this);
};
changer(ev) {
this.setState({ feeling: ev.target.val });
};
render() {
const { feeling } = this.state
return (
<div>
<input value={feeling} onChange={this.changer} />
<p>MARO fleels {age} now!</p>
</div>
);
};
};
少し話がそれますが、とあるコーディング師匠から「stateは状態や可変のもの」を指し、Propsは「性質や不変なもの」と、覚えると分かりやすいと教えていただきました。stateは「腹減った・・・」とか、状態を示し、Propsは「目の色、生物学的な性別」だったりします。
話がぶっとびましたが、次のコードはReact Hooksにより上記より可読性の良くなったコードになります。
import React, { useState } from 'react';
const ExComponent: React.FC = () => {
const [feeling, setFeeling] = useState('');
const changer = (ev) => {
setFeeling(ev.target.value);
};
return (
<div>
<input value={feeling} onChange={changer} />
<p>I'm {feeling}</p>
</div>
);
};
注目すべきはconst [feeling, setFeeling] = useState(”);この部分とsetFeeling(ev.target.value)の部分になります。上下で比較するとソースの可読性が一気に向上します。もちろん最初のコード、最後のコードどちらも同様に動作します。同じものなら読みやすい方が保守性も高まりますね。
副作用フック編
ステータスフックに比べると分かりやすいのでこちらから習得するのがおすすめです。
さきほど可読性が良くなりました、と書きましたがぶっちゃけ数行の話でいまいち賛同が得られないかもしれません。今回はきっと、「確かに」と思ってもらえるかもしれません。次のコードを見てください。一番分かりやすいのでReact公式サイトから持ってきました。
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
componentDidMount() {
document.title = `You clicked ${this.state.count} times`;
}
componentDidUpdate() {
document.title = `You clicked ${this.state.count} times`;
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
特に注目すべきは、
componentDidMount() {
document.title = `You clicked ${this.state.count} times`;
}
componentDidUpdate() {
document.title = `You clicked ${this.state.count} times`;
}
の部分でしょう。componentDidMount()、componentDidUpdate() 関数内で全く同じコードが2回登場してしまっています。これはメンテナンスや運用を考えると2度手間ですし、ミスが発生しやすくなる原因ともなり得ますね。そこで、副作用フックを用いたコードを見てみましょう。
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
今回の比較はだいぶ可読性が実感出来ると思います。何より無駄にすら思えてしまう2か所の記述が一つにまとめられ、メンテナンス性も大幅に上がっているのではないでしょうか。
注目ポイントは
useEffect(() => {
document.title = `You clicked ${count} times`;
});
でしょう。componentDidMount()、componentDidUpdate()の関数を一つにまとめることが出来ています。ご存じの方も多いかと思いますが、他にもcomponentWillUnmount()も併用することがあるので3つまとめてこの3行に凝縮することが可能です。
基本となる型
ステートフックと副作用フックですが、それぞれ基本となる書き方(文法)を覚えておけばさほど躓くことはないかと思います。
ステートフック(stateフック)のスニペット
const [count, setCount] = useState('banana');
・
・
・
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
1行目のuseState()については「“分割代入 (destructuring)”」という構文で、下記と同義になります。
var fruitStateVariable = useState('banana'); // Returns a pair
var fruit = fruitStateVariable[0]; // First item in a pair
var setFruit = fruitStateVariable[1]; // Second item in a pair
かなーり便利ですね!
副作用フック(effectフック)のスニペット
useEffect(() => {
document.title = `You clicked ${count} times`;
});
実はまだあるReact Hooks
今回は代表的でアプリケーションの基幹に密接に関係しがちな、ステートフックと副作用フックについてまとめてみましたが、React、React NativeにはまだまだReact Hooksがあります。ここで紹介すると何文字になるか分からないのでまた別の機会に!よかったらサイトをブックマークして続報をお待ちくださると、おじさん喜びMAXになります。
可読性とメンテのしやすさ抜群のReact Hooks
以上、ご紹介しましたReact Hooks、React Native Hooksでしたが、非常に簡単な仕組みで最大限の効率を得られるものだと感じています。
シンプルにコードをだれが修正しても運用が止まらないようにすることはエンジニアの宿命ですから、こういった便利で割と新しい技術はどんどん取り入れて、トライアンドエラーの精神でがんばりましょう!みなさん、お疲れ様でした!