Closed2

reactのRFC "useEvent" を追う

sh1mash1ma

掻い摘んで説明文章を書く コードは適宜下記から引用する

rfcs/0000-useevent.md at useevent · reactjs/rfcs

useEventってなに? - 参考

"安定したアイデンティティを持つイベントハンドラ"を提供するフック

  • イベントハンドラというのはイベントをハンドリングする関数のこと(合ってる?)
  • "安定したアイデンティティを持つイベントハンドラ"とは?
    • 要するに同じ関数オブジェクト
  • 依存配列(useEffectuseCallbackの第2引数と同樣のもの)は必要ない

何故これが必要?- 参考

stateやpropsを読むためにイベントハンドラをcomponent内に置くと最適化が壊れるから

例を示す。以下のtextはどこかから書き換えられ、SendButtonをクリックすると最新のtextsendMessage()する。

function Chat() {
  // このtextはどこかから書き換えられる
  const [text, setText] = useState('');

  // point: onClickはtextが変更されるたびに異なる関数になる
  const onClick = () => {
    sendMessage(text);
  };

  return <SendButton onClick={onClick} />;
}

pointの説明にある通り、onClick()textが変更されるたびに別の関数になってしまう。(textが変わる際のレンダリング前とあとでは別物の関数になっている)。

この手の問題の解決策と言われて真っ先に思い浮かぶのはuseCallback()を使うことだが、このケースでは使えない。何故ならばuseCallback()の第2引数である依存配列にtextを置く必要があるためだ。textの変更を検知してonClick()は再定義されるのだから、結局text更新のたびに違う関数になってしまう。

function Chat() {
  const [text, setText] = useState('');

  // point: 依然として、onClick()はtextが変更されるたびに異なる関数になる
  const onClick = useCallback(() => {
    sendMessage(text);
  }, [text]);

  return <SendButton onClick={onClick} />;
}

useEvent()textを"見る"(これは見るだけ、ということ?)ことができる。以下のコードはtextを見ている安定したイベントハンドラを提供できる

function Chat() {
  const [text, setText] = useState('');

  // textが変わってもonClickはずっと同じ関数!
  const onClick = useEvent(() => {
    sendMessage(text);
  });

  return <SendButton onClick={onClick} />;
}
このスクラップは2023/05/10にクローズされました