React開発者のみなさん、React Hooks使ってますか?
フック (hook) は React 16.8 で追加された新機能です。state などの React の機能を、クラスを書かずに使えるようになります。
2020/2/6に正式版としてリリースされたReact 16.8から、React Hooksという便利すぎる機能が使えるようになりました。
Reactを使い始めたばかりでも経験が長くても、意外と敬遠している人が多いんじゃないかな?と思います。
ということでこんにちは、株式会社Playground Webシステム開発部の稲垣です!
僕も最初は「Reactのライフサイクルすらよく分かってないのに新しい機能に手を出すのは危険や…」と思っていましたが、Reactに慣れてきて、いざ使ってみると「最高」でした。
もっとHooks広まれ!ってことで今回はReact Hooksを使うメリットとよく使うフックを紹介します。
React Hooksを使う3つのメリット
人によって感じ方は違うと思いますが、僕がReact Hooksを使って嬉しかったことは以下の3つです。
- クラスコンポーネントを減らせる
- react-reduxと併用したときにコンテナーコンポーネントを減らせる
- propsのバケツリレーを減らせる
減らせる減らせるばっかりですが、つまるところ以下を少なくできるわけですね。
- コード量
- ファイル数
- ファイルの密結合
どれも開発者にとっては嬉しいことばかり。
React Hooksを使うメリット1|クラスコンポーネントを減らせる
大前提として、Reactには2種類のコンポーネントが存在します。
- Class Component
- Functional Component
Class Componentとは
Class Componentはstateやライフサイクルを持ちます。
Reactのチュートリアルでよく見るコンポーネントですね。
以下、例。
import React, {Component} from 'react';
export default class App extends Component {
render() {
return (
<div>hoge</div>
)
}
}
Functional Componentとは
一方、stateは持たずに純粋にViewだけを記述するのがFunctional Componentでした。
Class Componentに比べて記法がスッキリしていて、最近のReact界隈では「なるべくFunctional Componentで書こう」という流れがあります。
import React from 'react';
const App = () => {
return (
<div>hoge</div>
)
}
export default App
React Hooksの登場によって起きたこと
Functional Componentでもstateやライフサイクルを持つことができます。
制約上、今までClass Componentとして記述していたコンポーネントを、Hooksを使ってFunctional Componentにすることでコードの見通しがよくなりました。
React Hooksを使うメリット2|コンテナーコンポーネントを減らせる【react-redux使用時】
Reduxと併用してReactで開発する場合、Storeが持つstateを参照したり、Actionでstateを変更できるようにするためには「コンテナーコンポーネント」を作る必要がありました。
React HooksのuseSelectorやuseDispatchを使うことで、コンテナーコンポーネントにしなくても良いケースが増えました。
極論ですが、Reduxを使っていても、コンテナーコンポーネントなしで開発することも可能です。
(逆に手間が増えるのでそんなことはしませんが)
React Hooksを使うメリット3|propsのバケツリレーを減らせる
これは特にreact-reduxを使ったWebアプリ開発の際に、「stateをStoreで一元管理できる」というReduxのメリットを最大限に活かせるようになったことです。
フックが無かった時代は、Reduxを使っていたとしても結局、コンテナーコンポーネントにmapしたstateを、propsとして子コンポーネントに渡していました。
後から詳しく紹介しますが、react-reduxのuseSelectorというメソッドを使うことで、ReduxでconnectしてないコンポーネントでもStoreのstateを参照できるのです。
React Hooksでできること|便利な4つのフックを紹介
今回はReact + Reduxを用いたWebアプリ開発でよく使う4つのフックを紹介します。
- クラス無しでstateを使えるuseState
- クラス無しでライフサイクルを使えるuseEffect
- connectしなくてもStoreを参照できるuseSelector
- connectしなくてもActionを呼び出せるuseDispatch
React Hooksならクラスを使わずにstateを扱える(useState)
Functional Componentでもstateを使いたい!という場合はuseStateのメソッドを使います。
以下は、チェックボックス用のコンポーネントの例です。
チェックボックスのチェック状態をstateに渡しています。
import React, {useState} from 'react';
const CheckBox = () => {
const [checked, setChecked] = useState(true);
return (
<input id="box1" type="checkbox" checked={checked}
onChange={e => setChecked(e.target.value)} />
<label for="box1">BOX1</label>
)
}
React Hooksならクラスを使わずにライフサイクルと同じことができる(useEffect)
useEffectというメソッドを使うと、Functional Componentでもライフサイクルメソッド(componentDidMount()やcomponentDidUpdate()など)と同じことができます。
以下は、外部JavaScriptのソースを読み込むためのコンポーネントです。
useEffectを使って、renderされてコンポーネントがマウントされた後に、<div>の要素を<script>要素に変更しています。
import React, {useEffect, useRef } from 'react';
const ScriptTag = (props) => {
const inputRef = useRef();
const id = Math.random().toString();
useEffect(() => {
const script = document.createElement("script");
script.src = props.src;
script.async = props.async || false;
script.defer = props.defer || false;
script.crossOrigin = props.crossOrigin || "";
script.innerHTML = props.innerHTML || "";
document.getElementById(id).replaceWith(script)
}, [inputRef]); // Only fired on Mount
return (
<div id={id} ref={inputRef} />
);
};
export default ScriptTag;
React HooksならReduxでconnectしなくてもStoreを参照できる(useSelector)
useSelectorを使うとconnectしてないコンポーネントでもStoreのstateを参照することができます。
以下は、Store内のuser.isLoggedInというBool型のstateを参照して、trueなら「You’re successfully logged in!」という表示をして、falseなら<Loading>というコンポーネントを呼び出しています。
import React from 'react'
import {useSelector} from "react-redux";
import {Loading} from "./components";
const App = () => {
const userState = useSelector(state => state.user);
return (
{(userState.isLoggedIn) ? (
<div>You're successfully logged in!</div>
) : (
<Loading />
)}
)
}
export default App
React HooksならReduxでconnectしなくてもActionを呼び出せる(useDispatch)
useDispatchというメソッドを使うと、Reduxで作ったActionをどのコンポーネントからでもDispatchすることができます。
さきほどの、ユーザーのログイン状態によって表示を変えるコンポーネントに、ユーザーがログインしていない場合、ログイン用ActionをDispatchする処理を追加しました。
import React from 'react'
import {useSelector, useDispatch} from "react-redux";
import {login} from "./modules/User/actions";
import {Loading} from "./components";
const App = () => {
const userState = useSelector(state => state.user);
const dispatch = useDispatch();
if (!userState.isLoggedIn) {
dispatch(login())
}
return (
{(userState.isLoggedIn) ? (
<div>You're successfully logged in!</div>
) : (
<Loading />
)}
)
}
export default App
こんな感じで、ほとんど全てのコンポーネントをFunctional Componentにすることができます。
Class Componentに比べてインデントの階層が浅いので、コードの見通しがよくなるので好きです。
皆さんもぜひReact Hooks使ってみてくださいね。
- 無料・簡単・片手でホームページを作成できる自社サービス Rakwi
- Web制作とアプリ開発を学べるオンラインプログラミング講座 Upstairs
- 開発,DX推進支援サービス スタートアッププラン