はじめに
Reactでは、コンポーネントを関数で定義する。
関数の外に書いた処理はいつ実行されているのか、実験結果をふまえて解説します。
// import文
// 初期処理 ←いつ実行されているのかわからない
function App() {
// 処理
return(
// 描画処理
)
}
export default App;
わかったこと
実験してみた結果わかったことは以下。
- 関数の外に記載した処理は、そのコンポーネントが外で
import
された時に実行される。 - ただし、そのコンポーネントが外で
import
されたとしても、import
のみで外の関数で利用されていない場合は、何も実行されない。
実験内容
単純にコンポーネントを呼び出してみる
「関数の外に記載した処理は、そのコンポーネントが外でimport
された時に実行される」ことがわかる実験結果を以下に示す。
以下のコードにより、App.tsx
の中でComponent1
とComponent2
を呼び出す。
ソースコード
// 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関数の後ろ");
console.log("Component1.tsx:Component1関数の前");
export const Component1 = () => {
console.log("Component1.tsx:Component1関数の中");
return <h2>コンポーネント1</h2>;
};
console.log("Component1.tsx:Component1関数の後ろ");
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
を更新し、再レンダリングする仕組みをつくる。
ソースコード
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関数の後ろ");
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関数の後ろ");
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行を消去する。
<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文
- 初回のみ実行したい処理
- 仮に定義しておく値
などを記載するのがよさそうだと思いました。