React Hooks登場でコンポーネントはどう変わった?
エンジニアになろう!
React Hooks とは?
「React Hooks」とは、React16.8より追加された新機能です。
これにより、クラスコンポーネントでしか使えなかった機能が、関数コンポーネントでも使えるようになりました。
【React 公式ドキュメント - フックの導入】
https://ja.reactjs.org/docs/hooks-intro.html
今回は、ReactHooks 登場前後のコンポーネントを比較し、「記法がどのように変わったのか」を見ていきたいと思います!
実装するサンプル
違いを分かりやすくするために、以下のような機能を持ったコンポーネントを実装します。
- 状態としてcount という変数を持つ
- カウントアップボタンを押すことで、count をインクリメントする
- count は常に画面上に表示する
- コンポーネントのマウント時・状態の更新時・アンマウント時に、それぞれコンソール出力する
それではさっそく、実装サンプルを見ていきましょう!
クラスコンポーネントで実装した場合
まずは、従来通り「クラスコンポーネント」で実装した場合です。
従来の React の記法に慣れた方にとっては、少し冗長な表記になるかもしれません。
1import React from "react";
2
3class NormalComponent extends React.Component {
4 /*
5 * コンストラクタ
6 */
7 constructor() {
8 super();
9
10 /**
11 * 画面の状態を初期化
12 */
13 this.state = {
14 count: 0,
15 };
16 }
17
18 /**
19 * コンポーネントマウント後処理
20 */
21 componentDidMount = () => {
22 console.log("[NormalComponent] componentDidMount");
23 };
24
25 /**
26 * コンポーネント更新時処理
27 */
28 componentDidUpdate = () => {
29 console.log("[NormalComponent] componentDidUpdate");
30 };
31
32 /**
33 * コンポーネントアンマウント前処理
34 */
35 componentWillUnmount = () => {
36 console.log("[NormalComponent] componentWillUnmount");
37 };
38
39 render = () => {
40 const { count } = this.state;
41 return (
42 <>
43 <p>{`This Component is NormalComponent (${count.toString()})`}</p>
44 <button
45 onClick={() => {
46 // ボタンを押下したタイミングでthis.setStateを使いstateを加算する
47 this.setState({ count: count + 1 });
48 }}
49 >
50 Count Up
51 </button>
52 </>
53 );
54 };
55}
56
57export default NormalComponent;
ここがポイント!
コンストラクタでコンポーネントの状態であるstate を初期化し、ボタン押下のタイミングでsetState を用いて更新します。
また、コンポーネントがマウント・アンマウントされたタイミングや、状態が更新されたタイミングはそれぞれcomponentDidMount ,componentWillUnmount ,componentDidUpdate といった React のライフサイクルメソッドを用いて検知し、コンソールに出力しています。
React Hooks を使った関数コンポーネントで実装した場合
続いて、「React Hooks」を使った実装パターンを見てみましょう。
React Hooks を使う際のルールとして、「関数コンポーネント中のトップレベル」で定義する必要があります。
1import React, { useEffect, useState } from "react";
2
3const HooksComponent = () => {
4 // マウントされたかどうかをisMountedで管理
5 const [isMounted, setIsMounted] = useState(false);
6 const [count, setCount] = useState(0);
7
8 // 第二引数に空の配列を設定することでマウント・アンマウント時のみ起動する
9 useEffect(() => {
10 // returnで関数を返却することで、
11 // useEffectの状態監視が終了した(=アンマウントされた)タイミングで起動する
12 return () => {
13 console.log("[HooksComponent] useEffect willUnmount");
14 };
15 }, []);
16
17 // 第二引数にcountを含めた配列を設定することで、countの変更を監視する
18 useEffect(() => {
19 // isMountedの状態によりクラスコンポーネントでの
20 // componentDidMountとcomponentDidUpdateを判別する
21 if (isMounted) {
22 console.log("[HooksComponent] useEffect disUpdate");
23 } else {
24 console.log("[HooksComponent] useEffect didMount");
25 setIsMounted(true);
26 }
27 }, [count]);
28
29 return (
30 <>
31 <p>{`This Component is HooksComponent (${count.toString()})`}</p>
32 <button
33 onClick={() => {
34 // ボタンを押下したタイミングでsetCountを使いcountを加算する
35 setCount(count + 1);
36 }}
37 >
38 Count Up
39 </button>
40 </>
41 );
42};
43
44export default HooksComponent;
クラスコンポーネントでの実装に比べると、全体的に記述量が減っているのが一目瞭然ですね。
ここがポイント!
useState
React Hooks では、useState でstate を定義しています。
this.state やthis.setState なしでstate が扱えます。
useEffect
useEffect で、関数コンポーネントでライフサイクルメソッド機能が使用可能になります。
クラスコンポーネントで使用した、以下の3つがまとまったものとイメージすれば分かりやすいでしょう。
- componentDidMount
- componentWillUnmount
- componentDidUpdate
isMounted
また、count に加えてisMounted という真偽値型の状態を持たせています。
関数コンポーネントでは、コンポーネントがマウント済みかどうかの状態を独自で持つ必要があるためです。
動作検証用コンポーネント
実際に、お手元の環境で上記コンポーネントの動作検証をする場合、以下をお使いください。
1import React from "react";
2import NormalComponent from "./NormalComponent";
3import HooksComponent from "./HooksComponent";
4
5export default class ComponentManager extends React.Component {
6 constructor() {
7 super();
8
9 this.state = {
10 showComponent: true,
11 };
12 }
13
14 render = () => {
15 const { showComponent } = this.state;
16 return (
17 <div>
18 <button
19 onClick={() => this.setState({ showComponent: !showComponent })}
20 >
21 {`Show/Hide Component`}
22 </button>
23 {showComponent ? (
24 <div>
25 <NormalComponent />
26 <HooksComponent />
27 </div>
28 ) : null}
29 </div>
30 );
31 };
32}
showComponent という状態を持ち、その値によってNormalComponent とHooksComponent の2種のコンポーネントのマウント・アンマウントを制御しています。
「Show/Hide Component」のボタンをクリックすると、各コンポーネントのマウント・アンマウント処理が正常に行われていることを確認できます。
さいごに
今回は、「React Hooks 登場前後のコンポーネントの違い」について解説しました。
クラスコンポーネントと React Hooks を用いた関数コンポーネントとでは、同じ挙動をさせる場合でも記法が大きく異なることが分かりますね。
両者とも基本の記法を覚えておけば、2つを組み合わせて複雑な処理を実現することが可能です。
ぜひ、しっかり覚えておきましょう!
こちらの記事もオススメ!
2020.07.17ライトコード的「やってみた!」シリーズ「やってみた!」を集めました!(株)ライトコードが今まで作ってきた「やってみた!」記事を集めてみました!※作成日が新し...
ライトコードでは、エンジニアを積極採用中!
ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。
採用情報へ
「好きを仕事にするエンジニア集団」の(株)ライトコードです! ライトコードは、福岡、東京、大阪、名古屋の4拠点で事業展開するIT企業です。 現在は、国内を代表する大手IT企業を取引先にもち、ITシステムの受託事業が中心。 いずれも直取引で、月間PV数1億を超えるWebサービスのシステム開発・運営、インフラの構築・運用に携わっています。 システム開発依頼・お見積もり大歓迎! また、現在「WEBエンジニア」「モバイルエンジニア」「営業」「WEBデザイナー」を積極採用中です! インターンや新卒採用も行っております。 以下よりご応募をお待ちしております! https://rightcode.co.jp/recruit