【React】関数コンポーネントの外に書いた処理はいつ実行されるのか

2021/11/03

(最終更新: 2022/7/31

アイキャッチ画像

はじめに

Reactでは、コンポーネントを関数で定義する。

関数の外に書いた処理はいつ実行されているのか、実験結果をふまえて解説します。

App.tsx
// import文
// 初期処理 ←いつ実行されているのかわからない

function App() {
    // 処理
    return(
        // 描画処理
    )
}

export default App;

わかったこと

実験してみた結果わかったことは以下。

  • 関数の外に記載した処理は、そのコンポーネントが外でimportされた時に実行される。
  • ただし、そのコンポーネントが外でimportされたとしても、importのみで外の関数で利用されていない場合は、何も実行されない。

実験内容

単純にコンポーネントを呼び出してみる

「関数の外に記載した処理は、そのコンポーネントが外でimportされた時に実行される」ことがわかる実験結果を以下に示す。

以下のコードにより、App.tsxの中でComponent1Component2を呼び出す。

ソースコード

App.tsx
// Component2→Component1の順でインポート
import { Component2 } from "./components/practicePage/Component2";
import { Component1 } from "./components/practicePage/Component1";

console.log("App.tsx:App関数の前");

function App() {
    console.log("App.tsx:App関数の中");
    
    return (
        <>
            <h1>App</h1>
            <Component1 />
            <Component2 />
        </>
    );
}
export default App;
console.log("App.tsx:App関数の後ろ");
Component1.tsx
console.log("Component1.tsx:Component1関数の前");
export const Component1 = () => {
    console.log("Component1.tsx:Component1関数の中");
    return <h2>コンポーネント1</h2>;
};
console.log("Component1.tsx:Component1関数の後ろ");
Component2.tsx
console.log("Component2.tsx:Component2関数の前");
export const Component2 = () => {
    console.log("Component2.tsx:Component2関数の中");
    return <h2>コンポーネント2</h2>;
};
console.log("Component2.tsx:Component2関数の後ろ");

実行結果

実行結果(コンソール)は以下のように表示された。

ブラウザのコンソール画面

ブラウザのコンソール画面

Component2.tsx:Component2関数の前
Component2.tsx:Component2関数の後ろ
Component1.tsx:Component1関数の前
Component1.tsx:Component1関数の後ろ
App.tsx:App関数の前
App.tsx:App関数の後ろ
App.tsx:App関数の中
Component1.tsx:Component1関数の中
Component2.tsx:Component2関数の中

解説

  • App.tsx中のimport { Component2 }実行時に、以下の処理が呼び出された。
    • Component2.tsx:Component2関数の前
    • Component2.tsx:Component2関数の後ろ
  • 次に、App.tsx中のimport { Component1 }実行時に、以下の処理が呼び出された。
    • Component1.tsx:Component1関数の前
    • Component1.tsx:Component1関数の後ろ

再レンダリング時にはどうなるか

先ほどの状況から、コンポーネントが再レンダリングされた場合は、

関数の中のみ実行される

コンポーネントをimportしたときに実行された、関数の外に記載した処理は実行されないことになる。

実験方法

再レンダリングが行われる条件は以下。

  • stateが更新されたとき
  • propsが変更されたとき
  • 親コンポーネントが再レンダリングされたとき

今回は、state変更ボタンを押したらstateを更新し、再レンダリングする仕組みをつくる。

参考:【React】レンダリングを制御するための関連知識メモ - エンジニアを目指す日常ブログ

ソースコード

App.tsx
import { Component2 } from "./components/practicePage/Component2";
import { Component1 } from "./components/practicePage/Component1";
import { useState } from "react";
console.log("App.tsx:App関数の前");

function App() {
    console.log("App.tsx:App関数の中");
    const [state, setState] = useState(0);
    return (
        <>
            <h1>App</h1>
            <button
                onClick={() => {
                    setState(state + 1);
                }}
            >state変更</button>
            <Component1 state={state}/>
            <Component2 state={state}/>
        </>
    );
}
export default App;
console.log("App.tsx:App関数の後ろ");
Component1.tsx
import { VFC } from "react";
console.log("Component1.tsx:Component1関数の前");
type Props = {state:number}
export const Component1:VFC<Props> = (props) => {
    const {state} = props;
    console.log("Component1.tsx:Component1関数の中");
    return <h2>{`コンポーネント1:${state}`}</h2>;
};
console.log("Component1.tsx:Component1関数の後ろ");
Component2.tsx
import { VFC } from "react";
console.log("Component2.tsx:Component2関数の前");
type Props = {state:number}
export const Component2:VFC<Props> = (props) => {
    const {state} = props;
    console.log("Component2.tsx:Component2関数の中");
    return <h2>{`コンポーネント2:${state}`}</h2>;
};
console.log("Component2.tsx:Component2関数の後ろ");

実行結果

state変更ボタンを押して再レンダリングさせると、コンソールに以下が追加表示される。

App.tsx:App関数の中
Component1.tsx:Component1関数の中
Component2.tsx:Component2関数の中

関数の中のみ実行されることがわかる。

importだけして呼び出さないとどうなるか

コンポーネントが外でimportされたとしても、importのみで外の関数で利用されていない場合は、何も実行されないことがわかる実験の結果を記載する。

ソースコード

App.tsxの以下2行を消去する。

App.tsx
            <Component1 state={state}/>
            <Component2 state={state}/>

実行結果

再読み込みすると、結果は以下のようになる。

App.tsx:App関数の前
App.tsx:App関数の後ろ
App.tsx:App関数の中
Line 10:10:  'Component2' is defined but never used  @typescript-eslint/no-unused-vars
Line 11:10:  'Component1' is defined but never used  @typescript-eslint/no-unused-vars

importしても利用しないコンポーネントの中身は実行されないことがわかる。 代わりに警告メッセージは表示されている。

まとめ

以下のことがわかった。

  • 関数の外に記載した処理は、そのコンポーネントが外でimportされた時に実行される。
  • (再レンダリング時は、importが走らないので実行されない)
  • ただし、そのコンポーネントが外でimportされたとしても、importのみで外の関数で利用されていない場合は、何も実行されない。

今回の結果から、関数の外には

  • import文
  • 初回のみ実行したい処理
  • 仮に定義しておく値

などを記載するのがよさそうだと思いました。



個別連絡はこちらへ→Twitterお問い合わせ

プロフィール

プロフィールイメージ

はち子

事業会社のシステム部門に異動して4年目の会社員。システム企画/要件定義/システムアーキテクチャ等。

Twitter→@bun_sugi

過去の記事について

はてなブログに掲載の記事(主にプログラミングメモ)についてはこちらに掲載しております。(本ブログに移行中)

タグ一覧

関連記事

Copyright© 2022, エンジニアを目指す日常ブログ

お問い合わせ|プライバシーポリシー