序章

この記事では、Reactの最新バージョン16.8の新機能である ReactHooksについて説明します。 React Hooksは機能であり、状態およびライフサイクルメソッドのモジュール式の代替として機能します。 クラスコンポーネントの代わりに、Reactフックを使用すると機能ベースのコンポーネントを構築できます。

前提条件

このチュートリアルを完了するには、Reactを理解している必要があります。 Reactの詳細については、Reactでコーディングする方法シリーズをご覧ください。

useState()メソッドの分析

クラスコンポーネントでは、Reactをindex.jsファイルにインポートし、クラスオブジェクトJustAnotherCounterのインスタンスを作成します。 状態と関数を追加して、プロパティcountを更新します。

index.js
import React, { Component } from 'react';

class ScoreCounter extends Component {
  state = {
    count: 0
  };

  setCount = () => {
    this.setState({ count: this.state.count + 1 });
  };

  render() {
    return (
      <div>
        <h1>{this.state.count}</h1>

        <button onClick={this.setCount}>Count Up To The Moon</button>
      </div>
    );
  }
}

renderライフサイクルメソッドでは、状態に保持されている値と、クリックするたびに関数を呼び出すボタンを返します。

ScoreCounterクラスコンポーネントを機能コンポーネントとして比較してみましょう。

React Hooksを使用すると、コードの行数を減らして、状態メソッドとライフサイクルメソッドをindex.jsファイルの機能コンポーネントに凝縮できます。 useStateを非構造化オブジェクトにインポートします。

[label index.js] 
import React, { useState } from 'react';

function ScoreCounter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <h1>{count}</h1>
      <button onClick={() => setCount(count + 1)}>Count Up To The Moon</button>
    </div>
  );
}

useState()メソッドは、状態オブジェクトを配列に分解し、その要素にhookを呼び出す値を割り当てます。 最初の要素は状態であり、2番目の要素は.setState()メソッドとして動作する関数です。 useState()メソッドに渡す引数は初期状態値として機能し、ここでは数値0がカウンターとして機能します。 初期状態値として、配列、オブジェクト、文字列、数値などの任意のデータ型を渡すことができます。

ボタンをクリックするたびに、setCount()関数は、1ずつ増加する引数として状態を渡します。

これで、ScoreCounter機能コンポーネントは、コードの可読性を優先して、より少ない構文をサポートします。

useState()メソッドを同じ関数で複数回使用することもできます。 index.jsファイルで、useStateをインポートし、機能コンポーネントLoginを宣言します。

index.js
import React, { useState } from 'react';

function Login() {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');

  return (
    <div className="login">
      <form>
        <label>
            Username: <input value={username} onChange={event => setUsername(event.target.value)}/>
            <br />
            Password: <input value={password} onChange={event => setPassword(event.target.value)}/>
          </label>
        <button>Submit</button>
      </form>
    </div>
  );
}

Login機能コンポーネントは、useState()メソッドを複数回使用して、フォームにユーザー名とパスワードを定義および設定し、各inputフィールドのロジックの概要を示します。

useState()を理解した上で、他のReactHookメソッドについて考えてみましょう。

useEffect()メソッドを使用する

React Hooksは、useEffect()メソッドを導入して、クラスコンポーネントのライフサイクルメソッドcomponentDidMountcomponentDidUpdate、およびcomponentWillUnmountを置き換えます。 このメソッドでは、ドキュメントオブジェクトモデルのコンテンツの変更やデータのフェッチなど、機能コンポーネントの副作用も許容されます。 useEffect()は、すべてのコンポーネントがレンダリングされた後に実行されます。

クラスのライフサイクルメソッド呼び出しを機能コンポーネントと比較してみましょう。

index.jsファイルで、useEffectScoreCounterコンポーネントにインポートします。

[label index.js] 
import React, { useState, useEffect } from 'react';

function ScoreCounter() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log(count); 
    document.title = `Your new score is ${count}`;
  });

  return (
    <div>
      <h1>{count}</h1>
      <button onClick={() => setCount(count + 1)}>Count Up To The Moon</button>
    </div>
  );
}

ここで、useEffect()は、コンソールにログインしてcountの初期状態値を確認し、ドキュメントオブジェクトモデルを更新するという副作用を引き起こします。

useEffect()はコンポーネントがレンダリングされるたびに実行されるため、2番目の引数である配列を設定して各インスタンスを格納し、値が変更された場合にメソッドを呼び出すことができます。

index.jsファイルで、useEffect()メソッドの2番目の引数として空の配列を適用します。

[label index.js] 
import React, { useState, useEffect } from 'react';

function ScoreCounter() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log(count); 
    document.title = `Your new score is ${count}`;
  }, []); 
}

ScoreCounterコンポーネントへのレンダリングごとに、useEffect()メソッドはcountの各インスタンスを配列に格納し、値が前の呼び出しと異なる場合はコンポーネントを更新します。 1回の呼び出しで、useEffect()は、componentDidMountおよびcomponentDidUpdateライフサイクルメソッドの機能を組み合わせます。

componentWillUnmountライフサイクルメソッドをシミュレートするには、index.jsファイルのuseEffect()メソッドで関数を返します。

[label index.js] 
import React, { useState, useEffect } from 'react';

function ScoreCounter() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log(count); 
    document.title = `Your new score is ${count}`;

    return () => console.log(`Component is unmounted`);
  }, []); 
}

useEffect()メソッドは、無名関数を宣言して返すことにより、1回の呼び出しでコンポーネントをアンマウントします。ここでは、console.logを使用して、そのステータスを確認します。

データをフェッチするには、useEffect()内でfetch を渡して、外部APIから情報を取得します。

index.jsファイルで、useStateuseEffectをインポートします。 GitHubUsers機能コンポーネントを宣言し、useEffectの本体内にfetchを渡します。

index.js
import React, { useState, useEffect } from 'react';

function GitHubUsers() {
  const [user, setUsers] = useState([]);

  useEffect(() => {
    fetch('https://api.github.com/users')
      .then(response => response.json())
      .then(data => {
        setUsers(data); // set users in state
      });
  }, []); 

空の配列として設定された2番目の引数に注意してください。 これは、useEffect()に1回実行するように通知するためのものです。 useEffect()メソッドはfetchを呼び出してGitHubAPI を呼び出し、応答をJSONオブジェクトに設定します。

呼び出しが成功したら、GitHubUsersコンポーネントにreturnステートメントを含めて、データを反復処理し、GitHubユーザー情報を出力します。

index.js
  return (
    <div className="section">
      {users.map(user => (
        <div key={user.id} className="card">
          <h5>{user.login}</h5>
        </div>
      ))}
    </div>
  );
}

useEffect()メソッドは、クラスコンポーネントの3つのライフサイクルメソッドすべての機能を1回の呼び出しで取得して、コンソールにログインし、ドキュメントオブジェクトモデルを更新し、外部APIからデータをフェッチします。

結論

useState()およびuseEffect()メソッドは、Reactライブラリへの強力な追加機能です。 React Hooksを使用すると、コードの短い行で状態メソッドとライフサイクルメソッドを使用して機能コンポーネントを最大化できます。

Reactフックの詳細については、Reactコンポーネントのフックを使用して状態を管理する方法の記事を参照してください。