Reactのコンポーネントの外側の処理の実行タイミング

Reactのコンポーネントの外側の処理の実行タイミング

Parent コンポーネントが ChildA および ChildB をインポートとしているとして、それぞれのコンポーネントで以下のように console.log() しているとどの順番に出力されるのか。

Parent.jsx

import { ChildB } from "./ChildB";
import { ChildA } from "./ChildA";

console.log("Parent | Outer Top");

export function Parent() {
  console.log("Parent | Inner");
  return (
    <>
      <ChildA />
      <ChildB />
    </>
  );
}

console.log("Parent | Outer Bottom");

ChildA.jsx

console.log("Child A | Outer Top");

export function ChildA() {
  console.log("Child A | Inner");
  return <></>;
}

console.log("Child A | Outer Bottom");

ChildB.jsx

console.log("Child B | Outer Top");

export function ChildB() {
  console.log("Child B | Inner");
  return <></>;
}

console.log("Child B | Outer Bottom");

結果 #

Child B | Outer Top
Child B | Outer Bottom
Child A | Outer Top
Child A | Outer Bottom
Parent | Outer Top
Parent | Outer Bottom
Parent | Inner
Child A | Inner
Child B | Inner

説明 #

よく考えてみると上記結果になるのは当然のことで、React だからとつい特別に考えてしまいがちですが、通常の JavaScript に還元して考えると、以下のコードを実行しているのと同じことです。

parent.js

import { childB } from "./childB";
import { childA } from "./childA";

console.log("Parent | Outer Top");

export function execParent() {
  console.log("Parent | Inner");
  execChildA();
  execChildB();
}

console.log("Parent | Outer Bottom");

childA.js

console.log("Child A | Outer Top");

export function execChildA() {
  console.log("Child A | Inner");
}

console.log("Child A | Outer Bottom");

childB.js

console.log("Child B | Outer Top");

export function execChildB() {
  console.log("Child B | Inner");
}

console.log("Child B | Outer Bottom");

import したとき、まずは import 先のコードの副作用が実行されます。

parentchildB そして childA の順番で import しているため、先に childB の副作用が実行されます。

Child B | Outer Top
Child B | Outer Bottom

次に childA の副作用が動きます。

Child B | Outer Top
Child B | Outer Bottom
Child A | Outer Top
Child A | Outer Bottom

また parent も別の上位モジュールから import されている存在です。そのため次に parent の副作用が動きます。

Child B | Outer Top
Child B | Outer Bottom
Child A | Outer Top
Child A | Outer Bottom
Parent | Outer Top
Parent | Outer Bottom

そしてついに上記モジュールから parentexecParent() が実行されます。

その中で execChildA() そして execChildB() の順番で実行されていますので、最終的な出力は以下となります。

Child B | Outer Top
Child B | Outer Bottom
Child A | Outer Top
Child A | Outer Bottom
Parent | Outer Top
Parent | Outer Bottom
Parent | Inner
Child A | Inner
Child B | Inner