JavaScript

【超便利】React Hooksを使う3つのメリットと便利機能4選

【超便利】React Hooksを使う3つのメリットと便利機能4選

React開発者のみなさん、React Hooks使ってますか?

フック (hook) は React 16.8 で追加された新機能です。state などの React の機能を、クラスを書かずに使えるようになります。

フックの導入 – React

2020/2/6に正式版としてリリースされたReact 16.8から、React Hooksという便利すぎる機能が使えるようになりました。

Reactを使い始めたばかりでも経験が長くても、意外と敬遠している人が多いんじゃないかな?と思います。

ということでこんにちは、株式会社Playground Webシステム開発部の稲垣です!

僕も最初は「Reactのライフサイクルすらよく分かってないのに新しい機能に手を出すのは危険や…」と思っていましたが、Reactに慣れてきて、いざ使ってみると「最高」でした。

もっとHooks広まれ!ってことで今回はReact Hooksを使うメリットとよく使うフックを紹介します。

React Hooksを使う3つのメリット

人によって感じ方は違うと思いますが、僕がReact Hooksを使って嬉しかったことは以下の3つです。

React Hooks3つのメリット
  1. クラスコンポーネントを減らせる
  2. react-reduxと併用したときにコンテナーコンポーネントを減らせる
  3. propsのバケツリレーを減らせる

減らせる減らせるばっかりですが、つまるところ以下を少なくできるわけですね。

ポイント
  • コード量
  • ファイル数
  • ファイルの密結合

どれも開発者にとっては嬉しいことばかり。

React Hooksを使うメリット1|クラスコンポーネントを減らせる

大前提として、Reactには2種類のコンポーネントが存在します。

Reactのコンポーネント
  1. Class Component
  2. 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つのフックを紹介します。

よく使う4つのフック
  1. クラス無しでstateを使えるuseState
  2. クラス無しでライフサイクルを使えるuseEffect
  3. connectしなくてもStoreを参照できるuseSelector
  4. 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使ってみてくださいね。

ABOUT ME
稲垣 貴映
サーバーエンジニア兼Webフロントエンジニア。 新卒で独立系SIerに入社後、金融系システム基盤の構築・運用を3年間経験。 プログラミングを独学していた頃に、CEOの馬谷が開講していたSwiftスクールに通い、2019年9月に入社。 趣味はブラジル音楽の演奏。

COMMENT

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA