📽️

ReactのRefsとStateを5秒の動画で理解する

2021/11/21に公開

最初の2回はコンポーネントを再レンダリングせずに、3回目にクリックすると、このボタンをdisableにするにはどうすればいいでしょうか?

<button disabled={count === 3}>Button</button>

Refsによる値の保存

When you want a component to “remember” some information, but you don’t want that information to trigger new renders, you can use a ref—it’s like a secret “pocket” for storing information in your component!
「コンポーネントに情報を「記憶」させたいが、その情報が新たなレンダリングのトリガーになることは避けたい場合、refを使用することができます。これは、コンポーネントに情報を保存するための秘密の「ポケット」のようなものです。」
React Docs - Referencing Values with Refs

stateではなく、refsでクリック数をカウントするようにしましょう。

コンポーネントのレンダリングとDOMの更新

ボタンを無効にするためには、reactはDOMを更新する必要があります。ReactがDOMを更新するのは、コンポーネントが以前とは異なる出力でレンダリングするときです。Reactは、Reactコンポーネントの1つがレンダリングするまで、DOMを更新しません。また、refを変更してもコンポーネントが再レンダリングされることはないので、ボタンはアクティブなままです。

この点をさらに実証するために、親コンポーネントを追加してみましょう。

デフォルトでは、Reactコンポーネントをレンダリングすると、そのすべての子を再帰的に再レンダリングします。そのため、Parentの状態を更新すると、ParentとComponentの両方がレンダリングされます。そして、Componentがレンダリングされると、Reactは条件を実行し、ボタンを無効にします。

<button disabled={count.current === 3}>Button</button>

しかし、ボタンを無効にするのに親の更新に頼ることはできません。この動作をComponentに直接実装してみましょう。

コンポーネントを再レンダリングするためにstateを更新する

状態を再導入することで、コンポーネントを再レンダリングさせることができます。しかし、最初の2回のクリックでコンポーネントをレンダリングしたくはありません。そこで、クリック数を静かにカウントするためのrefを残しておきます。そして、ボタンの状態を更新することだけを担当するstateを追加します。ボタンが3回目にクリックされたときだけbutttonStatusを更新するようにしましょう。

<button
  disabled={buttonStatus === 'disabled'}
  onClick={() => {
    count.current++
    if (count.current === 3) {
      setButtonStatus('disabled')
    }
  }}
>

記事の例は、refの動作を示すために作られています。不必要なレンダリングは必ずしも悪いことではなく、いちいち排除する必要はないことを覚えておいてください。実際には、実世界のシナリオでは、stateだけに頼って、このコンポーネントを3回再レンダリングする方が、シンプルで意味があるでしょう。しかし、アプリケーションの中では、さまざまな状況が発生します。refsを理解することは、コンポーネントの動作を微調整するための強力なツールとなります。

Discussion