Closed5

React のドキュメントを読む② - インタラクティビティの追加

ShionShion

イベントへの応答

イベントハンドラは副作用を持っていても構わない?

答えは Yes! 。
レンダー関数とは異なり、イベントハンドラは純関数 (pure function) である必要はないので、何かを変更する(入力値をタイプに応じて変更する、ボタンの押下に応じてリストを変更する、など)のに最適な場所である。
ただし、情報を変更するためには、まずそれを格納する方法が必要で、React では、これは stateを使用して行う。

イベント伝播

コンポーネントでボタンをレンダーしているとする。
そのボタンを押下してハンドラを発火させた時、コンポーネントを使用している親コンポーネントのハンドラも発火してしまうことがある。
以下の例では、PlayMovieを押下した時、Playing! の後に You clicked on the toolbar! が表示される。
伝播を防ぐにはe.stopPropagation()を使用する。

伝播する例

export default function Toolbar() {
  return (
    <div onClick={() => {
      alert('You clicked on the toolbar!');
    }}>
      <button onClick={() => alert('Playing!')}>
        Play Movie
      </button>
    </div>
  );
}

伝播を防ぐ例

export default function Toolbar() {
  return (
    <div onClick={() => {
      alert('You clicked on the toolbar!');
    }}>
      <button onClick={(e) => 
              {
                    e.stopPropagation(); // here!
                    alert('Playing!');
              }>
        Play Movie
      </button>
    </div>
  );
}
ShionShion

state:コンポーネントのメモリ

はじめてのフック

React では、useState やその他の use で始まる関数はフック (Hook) と呼ばれる。
フックは、React がレンダーされている間のみ利用可能な特別な関数。

ShionShion

レンダーとコミット

いつ、なぜ React はコンポーネントをレンダーするのか

React は以下のステップでレンダーする。

  1. レンダーのトリガ(お客様の注文を厨房に伝える)
  2. コンポーネントのレンダー(厨房で注文の品を料理する)
  3. DOM へのコミット(テーブルに注文の品を提供する)

ステップ 1:レンダーのトリガ

コンポーネントがレンダーされる理由には 2 つある。

  1. コンポーネントの初回レンダー
  2. コンポーネント(またはその祖先のいずれか)のstateの更新

アプリが開始するときには、初回のレンダーをトリガする必要がある。

import Image from './Image.js';
import { createRoot } from 'react-dom/client';

const root = createRoot(document.getElementById('root'))
root.render(<Image />);

また、コンポーネントが最初にレンダーされた後、set 関数を使って state を更新することで、さらなるレンダーをトリガすることができる。

ステップ 2:React がコンポーネントをレンダー

  • 初回レンダー時、React はルート (root) コンポーネントを呼び出す
  • 次回以降のレンダーでは、state の更新によってレンダーがトリガされた関数コンポーネントを、React が呼び出す

再レンダー時には、React は前回のレンダーからどの部分が変わったのか、あるいは変わらなかったのかを計算する。

ステップ 3:React が DOM への変更をコミットする

コンポーネントをレンダー(関数として呼び出し)した後、React は DOM を変更する。

  • 初回レンダー時には、React はappendChild()DOM API を使用して、作成したすべての DOM ノードを画面に表示する。
  • 再レンダー時には、React は最新のレンダー出力に合わせて DOM を変更するため、必要な最小限の操作(レンダー中に計算されたもの!)を適用する

React はレンダー間で違いがあった場合にのみ DOM ノードを変更する。

ShionShion

state 内のオブジェクトの更新

state を読み取り専用として扱う

state として格納するすべての JavaScript オブジェクトは読み取り専用として扱う必要がある。

機能しない(NG)例

const [position, setPosition] = useState({ x: 0, y: 0 });
position.x = 5;

機能する例

const [position, setPosition] = useState({ x: 0, y: 0 });

const update = () => {
    setPosition({ x: 5, y: 0 });
}
ShionShion

state 内の配列の更新

配列を書き換えずに更新する

slice と splice は名前が似ているものの、非常に異なるもの。

  • slice は配列や配列の一部をコピーする
  • splice は(要素の挿入や削除という)配列のミューテーションを行う

React では、state 内のオブジェクトや配列を書き換えたくないため、slice(p なし!)の方をより頻繁に使用する。

このスクラップは2024/03/10にクローズされました