Open1

ReactのuseEventを多重に使った場合の挙動

misukenmisuken

Hotな話題だったので見てみたら一つだけ気になる点。
https://twitter.com/misuken_now/status/1522172708473085952

たしか useLayoutEffect は子から親の順序で呼ばれるはずなので、以下のように親子関係のコンポーネントで useEvent が使用されると、親の関数が古い関数を参照しそうな気がしたが、イベント発火を useEffect で行っているから大丈夫なのだろう。
https://github.com/reactjs/rfcs/blob/useevent/text/0000-useevent.md#extracting-an-event-from-an-effect

function Page({ route, onVisit }) {
  // useEvent内のuseLayoutEffect(1)
  const mergedOnVisit = useEvent(visitedUrl => {
    // ...
    onVisit(visitedUrl);
  });

  // useEffect(3)
  useEffect(() => {
    mergedOnVisit(route.url);
  }, [route.url]);
  // ...
}

function Container({ route, currentUser }) {
  // useEvent内のuseLayoutEffect(2)
  const onVisit = useEvent(visitedUrl => {
    logAnalytics('visit_page', visitedUrl, currentUser.name);
  });
  return <Page onVisit={onVisit} />;
}

何らかの理由でイベントを useLayoutEffect で発火するようにしてしまうと(そうせざるを得ないシーンが有るかは不明)、親側では1つ古い関数が呼ばれて成立しなくなりそう?

function Page({ route, onVisit }) {
  // useEvent内のuseLayoutEffect(1)
  const mergedOnVisit = useEvent(visitedUrl => {
    // ...
    onVisit(visitedUrl);
  });

  // useLayoutEffect(2)
  useLayoutEffect(() => {
    mergedOnVisit(route.url);
  }, [route.url]);
  // ...
}

function Container({ route, currentUser }) {
  // useEvent内のuseLayoutEffect(3)
  const onVisit = useEvent(visitedUrl => {
    logAnalytics('visit_page', visitedUrl, currentUser.name);
  });
  return <Page onVisit={onVisit} />;
}