はじめに
まず本稿は「React Hooksとは」に重きを置いた記事のため
useEffectやuseStateなど各関数の詳細な説明や実装例は出てきません。
対象者はReact初学者で
「useEffectを学んでなんとなく実装はできるようになったけど。。。何が起きてるのかイマイチ理解できない」
という人に向けた内容となります。
useEffectを学ぶ前にまずReact Hooksについてザックリどんなものか理解しておくことで、今後の学習コストが少しでも下がればと思い執筆しています。
フック(hook)とは
そもそも「フック(hook)」とはどういう概念か。
あえてのwikipedia
フック(英: hook)は、プログラム中の特定の箇所に、利用者が独自の処理を追加できるようにする仕組みである。また、フックを利用して独自の処理を追加することを「フックする」という。
今時点ではぼんやり理解で問題なし。
Reactにおけるhook
React Hooksという機能がReact16.8で新たに追加された。
React Hooksが導入されたことで
↓
クラスコンポーネントでのみ使用できたstateやライフサイクルメソッド(=Reactの機能)が、関数コンポーネントでも使用できるようになった。可読性も向上。
【よく分からなければ先に「 補足」欄参照】
現時点において、どちらのコンポーネント手法を使っても基本同じことが実現できるが
クラスコンポーネントの記述の複雑度をはじめとした実装難易度の高さなどを踏まえると、関数コンポーネントでReact Hooksを使ったほうが圧倒的に楽というところが全て。
Reactの特徴を最大限活かすため、かつよりシンプルに記述するために
React Hooksを最大限活用して処理に組み込む必要がある。
補足
-
stateとは
Reactの特徴である「画面データの変更部分だけを検知しDOMに組み込む」という仮想DOMによる処理高速化を実現することができる
-
コンポーネントとは
「構成要素」「部品」「成分」
HTML要素を返す関数。独立した再利用可能なコード。
React では、マークアップ、CSS、JavaScript を組み合わせて、アプリの再利用可能な UI 要素であるカスタムの「コンポーネント」にすることができる。
↓
コンポーネントベースで設計・実装を行うことで様々なメリットが生じる。
Reactはコンポーネント指向を前提として作られており、非常に重要な概念となる。
(メリットの具体的な内容については記載割愛)
-
Reactにおけるライフサイクル
Reactの各コンポーネントにはライフサイクル(状態変化)があり、以下3つの主なフェーズで監視したり操作したりできる。-
マウント(Mounting):コンポーネントをDOMに入れる(描画する)
- constructor
- render
- ComponentDidMount
-
更新(Updating):stateなどの状態変化に応じてコンポーネントを更新
- render
- componentDidUpdate
-
アンマウント(Unmounting):コンポーネントがDOMから削除される
- componentWillUnmount
-
マウント(Mounting):コンポーネントをDOMに入れる(描画する)
-
クラスコンポーネントとは
React.Component を拡張する JavaScript クラス。
React16.8でhooksが登場するまでの間、「stateを使った内部状態の管理」「ライフサイクルメソッドが利用できる」などの利点があったことから、Reactにおける主流はクラスコンポーネントだった。
hooksが登場した今となっては、後述する関数コンポーネントでも同じことが実現できるようになり、「よりシンプルに実装できる」関数コンポーネントが主流となっている。
お互い一長一短はあるが、基本的には関数コンポーネント(React Hooks)を学ぶことをおススメする。(というか公式がそれを推奨している)
// クラスコンポーネントの書き方
import React from "react";
class App extends React.Component {
constructor(props) {
super(props);
this.state = { change: true };
}
render() {
return (
<div>
<button
onClick={() => {
this.setState({ change: !this.state.change });
}}
>
label
</button>
{this.state.change ? (
<h1>h1_1</h1>
) : (
<h1>h1_2</h1>
)}
</div>
);
}
}
export default App;
-
関数コンポーネントとは
記述がよりシンプルになった書き方。
シンプル故できればこちらを使いたかったが、状態管理の機能を持たせるためにはどうしてもクラスコンポーネントを使用せざるを得なかった。
※厳密には関数コンポーネントでも「高階コンポーネント」などの手法を使って実現はできたが、実装難易度が高く安易に手が出しづらい代物だった。
// 関数コンポーネントの書き方
import React from "react";
function GeeksforGeeks() {
return (
<div>
<h2>h2</h2>
<p>p</p>
</div>
);
}
export default function App() {
return (
<div className="App" >
<h2 style={{ color: 'green' }}>h2</h2>
<GeeksforGeeks />
</div>
)
}
フックを使うことによるメリット
フックを使用すると、コードの再利用性が向上し、複雑なコンポーネントを小さな関数に分割しやすくなります。
- よりシンプルでクリーンなコード
- 複雑なUIに適している
- 保守性の向上
とまあ様々利点はあるが、今時点では「結局記述が楽だから」でOK
React Hooksの種類
※各関数の詳細な説明・実装例については別記事で紹介。
~~作成次第ここに記事URL貼ります~~
stateやライフサイクルメソッドを実装するにあたり、簡単に実装できる機能がReact Hooksには備わっている。
(これら機能の登場により、Reactの学習コストがぐっと下がった)
機能は以下7種類に分類され、それぞれに関数が用意されている。
ここでは分類とともに、それぞれに紐づく主要な関数を紹介する。
State Hooks
情報を保存し、情報へのアクセスを提供
- useState:状態変数に直接更新アクセスを提供
- useReducer:reducer 関数の更新ロジックとともに状態変数を提供
const [count, setCount] = useState(0)
Context Hooks
prop として渡されることなく情報にアクセスすることを可能にする
- useContext:コンポーネントツリーで props を渡すことで、データをグローバルデータとして共有
const [count, setCount] = useState(0)
Ref Hooks
DOM ノードなどのレンダリングに使用されない情報を含む変数を作成
- useRef:DOM要素(主にDOMノード)への参照を宣言
const textRef = useRef(null);
Effect Hooks
エフェクトはコンポーネントを接続し、システムと同期させる。
これには、ブラウザーの DOM、ネットワーク、その他のライブラリの変更が含まれる。
- useEffect:コンポーネントを外部システムに接続
useEffect(()->{
// Code to be executed
}, [dependencies] )
Performance Hooks
パフォーマンスフックは、不要な作業をスキップし、レンダリングのパフォーマンスを最適化する方法。
- useMemo:不要な計算を減らすメモ化された値を返す
- useCallback:依存関係が変更された場合に変更されるメモ化されたコールバックを返す
const memoizedValue = useMemo(functionThatReturnsValue, arrayDependencies)
Resource Hooks
これにより、コンポーネントは、スタイリングへのアクセスやpromiseの読み取りなど、状態の一部にならずリソースへアクセスできる。
- use:コンテキストや promise などのリソースの値を読み取るために使用
const data = use(dataPromise);
Other Hooks
これらはめったに使用されないフックであり、主にライブラリで使用される。
- useDebugValue:デバッグするときに役立つらしい
おわりに
React Hooksについての超ざっくり解説でした。
この辺りは普通にググったら無限に記事が出てくるので、是非調べてみて勉強してみてください。
hooksの各関数やReactのライフサイクルメソッドについて、別途記事を作成中です。
作成次第、本稿内にリンクを貼っていきます。