5.1 イベントオブジェクト

function Form() {
  function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();
  }

  return <form onSubmit={handleSubmit}>...</form>;
}

5.2 イベント伝播

イベントは子から親へバブリングする。

<div onClick={() => console.log("親")}>
  <button
    onClick={event => {
      event.stopPropagation();
      console.log("子");
    }}
  >
    実行
  </button>
</div>

伝播停止を多用するより、明示的なコールバック設計を優先する。

5.3 state更新のバッチ処理

同一イベント内の複数state更新はまとめて処理される。

setSaving(true);
setError(null);
setMessage("保存中");

レンダリング回数を手動で予測するより、「各レンダリングは一貫したスナップショットを参照する」と理解する。

5.4 オブジェクトstate

type FormState = {
  name: string;
  email: string;
};

const [form, setForm] = useState<FormState>({
  name: "",
  email: "",
});

function updateField<K extends keyof FormState>(
  key: K,
  value: FormState[K]
) {
  setForm(current => ({
    ...current,
    [key]: value,
  }));
}

5.5 遅延初期化

重い初期値計算は関数として渡す。

const [settings] = useState(() => loadInitialSettings());

useState(loadInitialSettings())では、レンダリングのたびに関数が評価される。