コンポーネントの再レンダリングに関する問題の調査
Reactで再レンダリングが行われるのは、コンポーネントの状態やプロパティの変更、一元化された状態への更新、または親コンポーネントが再レンダリングされてすべての子コンポーネントで再レンダリングがトリガーされるときです。
最新の情報をユーザーに反映するには再レンダリングが不可欠ですが、必要以上に再レンダリングを行うと、アプリのパフォーマンスとユーザーインターフェイス(UI)の滑らかさ(UIのスムーズな動きと応答性)に大きな影響を与える可能性があります。
Vegaアプリでの再レンダリングの問題の調査には、why-did-you-renderを使用できます。これは、不要な再レンダリングの特定に役立つツールです。
このページでは、Vegaアプリでの再レンダリングの問題を調査する際に、why-did-you-renderをセットアップして使用する手順について説明します。
why-did-you-renderのセットアップ
why-did-you-renderを使用しないでください。詳細については、why-did-you-renderのドキュメントをご覧ください。手順1: アプリプロジェクトにwhy-did-you-renderをインストールする
npm install @welldone-software/why-did-you-render@8.0.3 --save-dev
why-did-you-renderをインストールすると、Reactコンポーネント内の不要な再レンダリングの特定に役立つ重要なデバッグツールがプロジェクトに追加され、アプリのパフォーマンスを最適化できるようになります。
コマンドを実行すると、package.jsonファイルのdevDependenciesセクションにwhy-did-you-renderパッケージが追加されて表示されます。パッケージファイルは、プロジェクトディレクトリのnode_modulesフォルダに追加されます。
手順2: アプリのbabel.config.jsにwhy-did-you-renderプラグインを追加する
以下の構成をアプリのbabel.config.jsに追加します。
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
env: {
development: {
plugins: [['@babel/plugin-transform-react-jsx', { runtime: 'classic' }]],
},
},
}
この構成により、why-did-you-renderパッケージとの互換性が保証されます。
手順3: wdyr.tsxファイルを作成する
/// <reference types="@welldone-software/why-did-you-render" />
import React from "react";
if (process.env.NODE_ENV === "development") {
const whyDidYouRender = require("@welldone-software/why-did-you-render");
whyDidYouRender(React, {
trackAllPureComponents: true,
});
}
wdyr.tsxファイルを作成することにより、why-did-you-renderの一元的な構成を設定し、特定の設定でのライブラリ初期化と、アプリ全体での動作制御ができるようになります。
wdyr.tsxファイルは、why-did-you-renderのトラッキング動作を構成するエントリファイルです。
trackAllPureComponents構成では、Pure React コンポーネントのトラッキングのみが可能になります。
アプリコード内のその他のコンポーネントをトラッキングするには、コンポーネントのwhyDidYouRenderをtrueに設定します。
例:
const MyCustomComponent = (props) => (
<div>
My Custom Component
</div>
);
MyCustomComponent.whyDidYouRender = true;
export default MyCustomComponent;
コンポーネントのトラッキングとその他のオプションについて詳しくは、why-did-you-renderのドキュメントをご覧ください。
手順4: wdtr.tsxをアプリのindex.jsにインポートする
import './wdyr';
import { AppRegistry, LogBox } from 'react-native';
import App from './src/Home';
import { name as appName } from './app.json';
//その他のアプリコード
AppRegistry.registerComponent(appName, () => App);
wdtr.tsxをアプリのindex.jsファイルにインポートすると、why-did-you-renderがフックを適切に設定し、アプリ全体のコンポーネントレンダリングをトラッキングできるようになります。
手順5: アプリをデバッグモードで実行し、why-did-you-renderのログを調べる
- アプリをデバッグモードで実行します。手順については、Vega Studioのセットアップと使用方法を参照してください。
- スクロールなどのアクションをアプリで実行します。
- アプリログに表示される
why-did-you-renderのログを調べます。アプリログの表示方法については、ログの表示を参照してください。 - 再レンダリング中のコンポーネントのレンダリングの理由を分析します。
- 根本的な原因を修正して、不要な再レンダリングを排除してください。
why-did-you-renderのログ出力の例
(NOBRIDGE) GROUP SpatialNavigationVirtualizedList
(NOBRIDGE) LOG {"SpatialNavigationVirtualizedList": [Function anonymous]} Re-rendered because of props changes:
(NOBRIDGE) GROUP props.renderItem
(NOBRIDGE) LOG different functions with the same name. (more info at http://bit.ly/wdyr02)
(NOBRIDGE) LOG {"prev renderItem": [Function renderItem]} !== {"next renderItem": [Function renderItem]}
(NOBRIDGE) GROUP Rendered by Grid
(NOBRIDGE) LOG {"Grid": [Function Grid]} Re-rendered because of hook changes:
(NOBRIDGE) GROUP [hook useState result]
(NOBRIDGE) LOG different objects. (more info at http://bit.ly/wdyr3)
(NOBRIDGE) LOG {"prev ": ""} !== {"next ": "Unnecessary State Update!"}
(NOBRIDGE) GROUP SpatialNavigationVirtualizedList
(NOBRIDGE) LOG {"SpatialNavigationVirtualizedList": [Function anonymous]} Re-rendered because of props changes:
(NOBRIDGE) GROUP props.renderItem
(NOBRIDGE) LOG different functions with the same name. (more info at http://bit.ly/wdyr02)
(NOBRIDGE) LOG {"prev renderItem": [Function renderItem]} !== {"next renderItem": [Function renderItem]}
(NOBRIDGE) GROUP Rendered by Grid
(NOBRIDGE) LOG {"Grid": [Function Grid]} Re-rendered because of hook changes:
(NOBRIDGE) GROUP [hook useState result]
(NOBRIDGE) LOG different objects. (more info at http://bit.ly/wdyr3)
(NOBRIDGE) LOG {"prev ": ""} !== {"next ": "Unnecessary State Update!"}
(NOBRIDGE) GROUP SpatialNavigationVirtualizedList
(NOBRIDGE) LOG {"SpatialNavigationVirtualizedList": [Function anonymous]} Re-rendered because of props changes:
(NOBRIDGE) GROUP props.renderItem
(NOBRIDGE) LOG different functions with the same name. (more info at http://bit.ly/wdyr02)
(NOBRIDGE) LOG {"prev renderItem": [Function renderItem]} !== {"next renderItem": [Function renderItem]}
(NOBRIDGE) GROUP Rendered by Grid
(NOBRIDGE) LOG {"Grid": [Function Grid]} Re-rendered because of hook changes:
(NOBRIDGE) GROUP [hook useState result]
(NOBRIDGE) LOG different objects. (more info at http://bit.ly/wdyr3)
(NOBRIDGE) LOG {"prev ": ""} !== {"next ": "Unnecessary State Update!"}
このログの例では、useEffectフック内で更新が行われたため、Gridコンポーネントが再レンダリングされていることがわかります。
Gridコンポーネントの再レンダリングを解決するには、useEffectフック内の不要な状態更新を削除します。
useEffect(() => {
setHeaderTitle("Unnecessary State Update!");
}, []);
関連トピック
Last updated: 2025年9月30日

