関数コンポーネントは素晴らしいですが、プロパティによって伝えられたことを正確に実行するように制限されています。 それらの状態に注意する必要がある瞬間、それらをクラスコンポーネントとして書き直す必要があります。 幸いなことに、多くのクラスコンポーネントのみの機能がコンポーネントを機能させるようになっています。

現在アルファ版であり、React v16.7に搭載される予定のそのような機能の1つは、フックです。 フックは、以前はクラスコンポーネントから関数コンポーネントにのみ使用可能であったステートフルネスとライフサイクルメソッドをもたらします。

入門

前述のように、この機能は現在アルファ版ですが、Reactの次のポイントリリースの一部になる予定です。 このため、プロジェクトにReactを追加するときにバージョンを指定する必要があります。

# Via npm
$ npm install --save [email protected] [email protected]

# Or via Yarn
$ yarn add [email protected] [email protected]

フックを作るものは何ですか?

  • useという単語で始まる必要があります。
  • フックは、関数コンポーネントおよびカスタムフック内からのみ呼び出すことができます。 これには、コンポーネントロジックを適切にグループ化しておくという追加のボーナスがあります。
  • フックはトップレベルでのみ使用してください。関数コンポーネント内の条件、ループ、またはネストされた関数の内部からは使用しないでください。 これは、各レンダリングでフックが同じ順序で呼び出されるようにするためです。

コンポーネントの状態

フックを使用してステートフル関数コンポーネントを作成するには、ReactパッケージのuseStateを使用してステートを初期化する必要があります。

このメソッドは、初期状態を設定するためのパラメーターを受け取り、現在の状態を含む配列と状態を設定するための関数を返します。

ボタンが押されるたびにランダムに設定される色を追跡するステートフル関数コンポーネントは次のとおりです。

import React, { useState } from "react";
import { render } from "react-dom";

function StatefulFn() {
  const [color, setColor] = useState(false);

  function onClick() {
    const colors = [
      "#008F68",
      "#6DB65B",
      "#4AAE9B",
      "#FAE042",
      "#EFBB35",
      "#DFA612"
    ];

    setColor(colors[Math.floor(Math.random() * colors.length)]);
  }

  return (
    <button onClick={onClick} style={{ backgroundColor: color }}>
      Click to Change Button Color
    </button>
  );
}

const container = document.createElement("div");
document.body.appendChild(container);
render(<StatefulFn />, container);

useStateメソッドは、単一の値で使用することを目的としており、クラスコンポーネントの動作方法である状態オブジェクトではありません。 このため、状態オブジェクトを手動で維持するか、より簡単に言えば、useStateを複数回呼び出して、状態内の各変数を追跡する必要があります。

const [color, setColor] = useState(false);
const [size, setSize] = useState('medium');
const [reptile, setReptile] = useState('alligator');


コンポーネントのライフサイクル

関数コンポーネントを使用するもう1つの落とし穴は、ライフサイクルメソッドがないことです。 フック機能のもう1つの部分は、componentDidMountcomponentDidUpdate、およびcomponentWillUnmountの組み合わせであるuseEffectの追加です。

より簡単に言えば、useEffectは、最初のレンダリングとその後の再レンダリングの後に起動します。

Reactクラスコンポーネントのライフサイクルに精通している場合は、renderメソッドに副作用のあるコードを含めるのは悪いことです。 そもそもライフサイクルメソッドが存在するのはそのためです。

そのような副作用の1つは、ネットワークリクエストを起動し、返された値で状態を更新することです。 次の例では、setTimeoutを使用して非常に遅いネットワーク接続をシミュレートし、待機中に読み込みメッセージを表示します。

import React, { useEffect, useState } from "react";
import { render } from "react-dom";

function EffectedFn() {
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    setTimeout(() => {
      setLoading(false);
    }, 1000 * 10);
  });

  return (
    <div>
      {loading && <span>Loading...</span>}
      {!loading && <span>All Done!</span>}
    </div>
  );
}

const container = document.createElement("div");
document.body.appendChild(container);
render(<EffectedFn />, container);

useEffectの優れた点は、componentDidMountcomponentDidUpdateのようにブラウザが画面を更新するのを妨げないことです。 これにより、ユーザーにとって物事が反応しやすく、きびきびと見えるようになります。

特に複数の状態変数を操作する場合にパフォーマンスをさらに向上させるために、useEffectに、特定の値が変更された場合にのみ起動するように指示できます。

useEffect(() => {
  setTimeout(() => {
    setLoading(false);
  }, 1000 * 10);
}, [loading]);

しかし、私はフックを使いたくありません!

フックの本当に素晴らしい点は、使用したくない場合は使用する必要がないことです。 クラスの使用に熱心な場合は、トラックインを続けることができます。 既存のフックされていない関数をすべて更新する必要があるのではないかと心配している場合は、更新しないでください。

フックは100%下位互換性があるため、既存のコードを更新するためにスクランブルをかける必要はありません。 クラスはどこにも行きません。フックを使い始める準備ができていれば、それをサポートするバージョンのReactを使用している限り、そうすることができます。

結論

個人的には、状態とライフサイクルのサポートが必要なときに関数をクラスに移植することにうんざりしているので、フックは非常に歓迎すべき追加です。

さらに、独自のフックを作成したり、より大きなReactコミュニティによって開発されたフックを使用したりするのは非常に簡単です。 をポップアップしている利用可能なフックコレクションがすでにあります。

あなたが私のようで、今日フックを使い始める準備ができていて、この記事のコードが実際に動作しているのを見たい場合は、CodeSandboxにアクセスしてください。