ReactにおけるRef操作のためのuseRefフック

このレッスンではrefを操作します。分かりやすくするために、useRefフックの動作をuseStateフックと比較しながら見ていきましょう。

ボタンを持つコンポーネントを作成しましょう:

App.jsxreturn (
  <div>
    <button>
      state click
    </button>
  </div>
);

コンポーネントにuseStateをインポートします:

App.jsximport { useState } from 'react';

そしてstateステートを定義します:

App.jsxconst [state, setState] = useState(0);

次に、ボタンをクリックするとstateが1ずつ増加するようにしましょう。ステートの値はボタンのテキスト内に直接表示します:

App.jsx<button onClick={handleStateClick}>
  state click: {state}
</button>

ボタンクリックを処理する関数handleStateClickを定義します:

App.jsxfunction handleStateClick() {
  setState(state + 1);
}

ボタンを何度かクリックし、ステートの値が増加するのを確認しましょう。

では次に、ステートではなくrefを使用してAppコンポーネントを作成しましょう。

まず、コンポーネントにuseRefをインポートします:

App.jsximport { useRef } from 'react';

そしてref refを定義します。useRefフックは、唯一のプロパティcurrentを持つrefオブジェクトを返します。このプロパティが以降で重要になります。初期値を0に設定します:

App.jsxconst ref = useRef(0);

ボタンにクリックハンドラを設定します。ref自体ではなく、そのプロパティcurrentを読み書きする必要があることを覚えておいてください:

App.jsx<button onClick={handleRefClick}>
  ref click: {ref.current}
</button>

ボタンクリックを処理する関数を追加します。ここでは、前のステートの例と同様にcurrentを1ずつ増やします。値の変更にsetState関数が必要なステートとは異なり、refのプロパティは直接操作します:

App.jsxfunction handleRefClick() {
  ref.current = ref.current + 1;
}

さて、ボタンをクリックしてみましょう。何が見えますか?クリックしても、最初の0の値が変わらないままです。

値が実際に変わっているのか疑問に思うかもしれません。これを確認してみましょう。クリックハンドラ関数に、currentの値をコンソールに出力するコード行を追加します:

App.jsxfunction handleRefClick() {
  ref.current = ref.current + 1;
  console.log('ref click: ' + ref.current);
}

ブラウザのコンソールを開き、再びボタンをクリックすると、クリックごとに値が実際に変化しており、何もトリックがないことが確認できます。

これで、ステートとは異なり、refの値の変更はコンポーネントの再レンダリングを引き起こさないことがわかりました。そのため、ボタンのテキストには毎回初期値の0が表示されたままなのです。

したがって、データがレンダリングに使用される場合はステートに保存し、レンダリングが必要ない場合は、refの使用がより効率的になる可能性があります。

Задание 1

テキスト'text'の段落とボタンを持つコンポーネントがあるとします。ボタンをクリックするたびに、段落のテキストの末尾に感嘆符が追加されるようにしてください。これをステートを使用して実装してください。

Задание 2

Appコンポーネントを作成しますが、今回はステートの代わりにrefを使用してください。ボタンを押しても段落のテキストが変更されないことを確認してください。また、段落のテキストをコンソールに出力するコードを追加し、コンソールを開いてテキストが実際に変更されていることを確認してください。