React hooksの書き方・使い方をサンプルコードで解説

React hooksの書き方をまとめております。

Reactの基礎的な書き方については別記事をご確認ください。

React.jsの基礎的な書き方まとめ

サンプルコードで書かれたReact.jsは、実行結果を出すためにCDNで処理しています。
ビルド環境とは一部記述が異なりますのでご注意ください。
利用CDNは以下。

<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<script crossorigin src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

React hooksとは

  • React hooksとは、関数型コンポーネントで状態管理を行う時に使用する
  • 状態管理とは、値に応じて処理や表示(UI等)を変えたい時のことを指す
  • コンポーネント内で取得・変更できる値をState(ステート)と呼ぶ
  • ステートは属性(props)と違い、コンポーネント内で変更できる

useState

  • useState()は、ステートの宣言と代入を行うことが出来る
  • 配列で変数名とその変数を書き換える関数をセットする
  • 初期値はuseState()の中に書く

useStateのインポート

import React, { useState } from 'react'
//React hooksを使う場合の必須記述
//このページではcdnで実行しているのでReact.useStateと書いて呼び出す

useStateの書き方

//const [変数, 変数を代入する関数] = useState(初期値);
//関数は「set変数名」と書くと分かりやすい
↓
const [count, setCount] = React.useState(0);

useStateを使用したサンプルコード

サンプルコード
<div id="app1"></div>

<script type="text/babel">
const App = () => {
    const [count, setCount] = React.useState(0);
    //import済みの場合は「React.」は不要でuseStateのみで書ける
    
    // renderしなくてもcountの値が変更されていることが分かる
    return (
        <div>
            <p>count:{count}</p>
            <input type="button" value="+1" onClick={() => setCount(count + 1)} />
        </div>
    )
}

ReactDOM.render(
    <App />,
    document.getElementById('app1')
);
</script>

useStateで配列の更新

  • useState()は配列も扱うことが出来る
  • ただしステートにプッシュしても自動レンダリングはされない
  • スプレッド構文で代入するなど工夫が必要
  • レンダリングされる繰り返し要素には一意(被らない)なkey属性を付けることが推奨されている
サンプルコード
<div id="app2"></div>

<script type="text/babel">
const App = () => {
    const [list, setList] = React.useState([]);
    const [text, setText] = React.useState('');
    
    const Add = () => {
        if(!text){
            alert('入力されていません。');
            return false;
        }
        
        //下記のように書いても変化がない判定となるため配列は追加されない
        //list.push(text);
        //setList(list);
        
        //スプレッド構文で配列を追加する
        setList([...list, text]);
        
        setText('');
    }
    
    //mapで配列を表示
    //第二引数でkeyを取得し、liにkey属性を付与させる(Reactの更新時に無駄なレンダリングを避けるため)
    return (
        <div>
            <input type="text" value={text} onChange={e => setText(e.target.value)} />
            <input type="button" value="メモを追加" onClick={() => Add()} />
            <ul>
            {
                list.map((value, key) => <li key={key}>{value}</li>)
            }
            </ul>
        </div>
    )
}

ReactDOM.render(
    <App />,
    document.getElementById('app2')
);
</script>

useStateでオブジェクトの更新

  • useState()はオブジェクトの更新もできる
  • ただし配列と同じくオブジェクトの属性を代入しただけではレンダリングされない
  • スプレッド構文で代入するなど工夫が必要
サンプルコード
<div id="app3"></div>

<script type="text/babel">
const App = () => {
    const [vote, setVote] = React.useState({
        mario : 0,
        luigi : 0,
    });
    
    //スプレッド構文でオブジェクトをマージ
    //オブジェクトのキーは、[]で変数を使用できるので、引数で受け取ったキャラ名を使用している
    const addVote = (character) => {
        setVote({...vote, [character] : (vote[character] + 1)});
    }
    
    return (
        <div>
            <p>マリオ:{vote.mario}</p>
            <p>ルイージ:{vote.luigi}</p>
            <input type="button" value="マリオに投票" onClick={() => addVote('mario')} />
            <input type="button" value="ルイージに投票" onClick={() => addVote('luigi')} />
        </div>
    )
}

ReactDOM.render(
    <App />,
    document.getElementById('app3')
);
</script>

useEffect

  • useEffect()は、レンダリング後に処理を行うことが出来る関数
  • 第一引数にuseEffectの処理を書く
  • 第二引数に配列で値を設定でき、指定した値が変化した場合のみ処理を行う形にも出来る

useEffectのインポート

import React, { useState, useEffect } from 'react'
//React hooksを使う場合の必須記述
//このページではcdnで実行しているのでReact.useEffectと書いて呼び出す
//複数インポートを行う場合はカンマ区切り

useEffectの書き方(デフォルト)

useEffect(() => {
    console.log('Hello, World!');
});

useEffectの書き方(特定の値が変化した場合のみ)

useEffect(() => {
    console.log('Hello, World!');
}, [count]);
//countが変化した場合のみ処理を行う

useEffectを使用したサンプルコード

検証からconsole.logで直接ご確認ください。
カウントが増えるたびに、「useEffect!」が発火していることが確認できます。

サンプルコード
<div id="app4"></div>

<script type="text/babel">
const App = () => {
    const [count, setCount] = React.useState(0);
    
    React.useEffect(() => {
        console.log('useEffect!');
    });
    
    return (
        <div>
            <p>count:{count}</p>
            <input type="button" value="+1" onClick={() => setCount(count + 1)} />
        </div>
    )
}

ReactDOM.render(
    <App />,
    document.getElementById('app4')
);
</script>

useEffectを使用したサンプルコード(空配列)

第二引数に空配列を指定すると、レンダリングされてもuseEffectが発火していないことが分かる。
これは、第二引数に値を指定しておらず、更新対象の値が存在しないため。
空配列を指定することで、最初のレンダリングのみ発火という形にできる。

サンプルコード
<div id="app5"></div>

<script type="text/babel">
const App = () => {
    const [count, setCount] = React.useState(0);
    
    React.useEffect(() => {
        console.log('useEffect no Array!');
    }, []);
    
    return (
        <div>
            <p>count:{count}</p>
            <input type="button" value="+1" onClick={() => setCount(count + 1)} />
        </div>
    )
}

ReactDOM.render(
    <App />,
    document.getElementById('app5')
);
</script>

useEffectを使用したサンプルコード(第二引数に配列指定)

第二引数に値を指定することが、その値の更新時のみuseEffectが発火という形で処理できる。
以下はcount2のみuseEffectが処理される。

サンプルコード
<div id="app6"></div>

<script type="text/babel">
const App = () => {
    const [count1, setCount1] = React.useState(0);
    const [count2, setCount2] = React.useState(0);
    
    React.useEffect(() => {
        console.log('useEffect!');
    }, [count2]);
    
    return (
        <div>
            <p>count1:{count1}</p>
            <input type="button" value="+1" onClick={() => setCount1(count1 + 1)} />
            <p>count2:{count2}</p>
            <input type="button" value="+1" onClick={() => setCount2(count2 + 1)} />
        </div>
    )
}

ReactDOM.render(
    <App />,
    document.getElementById('app6')
);
</script>

useRef

  • useRefは、コンポーネント内に値を保持する関数
  • ref属性を不要することで、DOMと連動できる
  • useStateと異なり、値が更新されても再レンダリングされない
  • 不要な再レンダリングを避けるためにも使用できる

useRefのインポート

import React, { useState, useEffect, useRef } from 'react'
//React hooksを使う場合の必須記述
//このページではcdnで実行しているのでReact.useRefと書いて呼び出す
//複数インポートを行う場合はカンマ区切り

useRefの書き方(宣言)

const inputDOM = useRef(); //useRefの中に初期値を入力できる

useRefの書き方(DOMの連動)

<input type="text" ref={inputDOM} />

useRefを使用したサンプルコード

useStateで配列の更新というサンプルコードを紹介していましたが、これは1文字入力の度にレンダリングが走っているため、極めて非効率です。

useRefを使うことで配列の追加時にのみレンダリングがされます。

console.logでチェックして頂くと、Add関数が発火した時のみuseEffectが動いていることが分かります。

サンプルコード
<div id="app7"></div>

<script type="text/babel">
const App = () => {
    const [list, setList] = React.useState([]);
    const inputDOM = React.useRef();
    
    React.useEffect(() => {
        console.log('insert!');
    });
    
    const Add = () => {
        if(!inputDOM.current.value){
            alert('入力されていません。');
            return false;
        }
        
        //スプレッド構文で配列を追加する
        setList([...list, inputDOM.current.value]);
        inputDOM.current.value = '';
    }
    
    return (
        <div>
            <input type="text" ref={inputDOM} />
            <input type="button" value="メモを追加" onClick={() => Add()} />
            <ul>
            {
                list.map((value, key) => <li key={key}>{value}</li>)
            }
            </ul>
        </div>
    )
}

ReactDOM.render(
    <App />,
    document.getElementById('app7')
);
</script>

以上、React hooksの書き方・使い方をサンプルコードで解説、でした。