React ライフサイクル
このガイドでは、Ionic React アプリケーションで Ionic ライフサイクルイベントを使用する方法について説明します。
Ionic ライフサイクルメソッド
Ionic は、アプリで使用できるいくつかのライフサイクルメソッドを提供します。
イベント名 | 説明 |
---|---|
ionViewWillEnter | ルーティング先のコンポーネントがビューにアニメーション表示される直前に発生します。 |
ionViewDidEnter | ルーティング先のコンポーネントのアニメーションが*完了*したときに発生します。 |
ionViewWillLeave | ルーティング*元*のコンポーネントがアニメーションを開始する直前に発生します。 |
ionViewDidLeave | ルーティング*元*のコンポーネントのアニメーションが*完了*したときに発生します。 |
これらのライフサイクルは、ルーターによって直接マッピングされたコンポーネントでのみ呼び出されます。つまり、`/pageOne` が `PageOneComponent` にマッピングされている場合、Ionic ライフサイクルは `PageOneComponent` で呼び出されますが、`PageOneComponent` がレンダリングする子コンポーネントでは呼び出されません。
これらのメソッドにアクセスする方法は、クラスベースのコンポーネントを使用しているか、関数型コンポーネントを使用しているかによって異なります。以下で両方の方法について説明します。
クラスベースのコンポーネントのライフサイクルメソッド
クラスベースのコンポーネントで Ionic ライフサイクルメソッドを使用するには、次のように `withIonLifeCycle` 高次コンポーネント (HOC) でコンポーネントをラップする必要があります。
export default withIonLifeCycle(HomePage);
`withIonLifeCycle` は `@ionic/react` からインポートされます。
その後、クラスコンポーネントに適切なライフサイクルメソッドを作成すると、イベントが発生したときに HOC がそのメソッドを呼び出します。以下は、各ライフサイクルメソッドが実装されたコンポーネント全体です。
import React from 'react';
import { IonHeader, IonPage, IonToolbar, IonTitle, IonContent, withIonLifeCycle } from '@ionic/react';
class HomePage extends React.Component {
ionViewWillEnter() {
console.log('ionViewWillEnter event fired');
}
ionViewWillLeave() {
console.log('ionViewWillLeave event fired');
}
ionViewDidEnter() {
console.log('ionViewDidEnter event fired');
}
ionViewDidLeave() {
console.log('ionViewDidLeave event fired');
}
render() {
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonTitle>Home</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent></IonContent>
</IonPage>
);
}
}
export default withIonLifeCycle(HomePage);
関数型コンポーネントのライフサイクルメソッド
Ionic React は、関数型コンポーネントで使用できる各ライフサイクルメソッドのフックをエクスポートします。各フックは、イベントが発生したときに呼び出されるメソッドを受け取ります。
import {
IonContent,
IonHeader,
IonTitle,
IonToolbar,
useIonViewDidEnter,
useIonViewDidLeave,
useIonViewWillEnter,
useIonViewWillLeave,
} from '@ionic/react';
import React from 'react';
const HomePage: React.FC = () => {
useIonViewDidEnter(() => {
console.log('ionViewDidEnter event fired');
});
useIonViewDidLeave(() => {
console.log('ionViewDidLeave event fired');
});
useIonViewWillEnter(() => {
console.log('ionViewWillEnter event fired');
});
useIonViewWillLeave(() => {
console.log('ionViewWillLeave event fired');
});
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonTitle>Home</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent></IonContent>
</IonPage>
);
};
export default HomePage;
関数型コンポーネントは、クラスコンポーネントのように `withIonLifeCycle` HOC でラップする必要はありません。
開発者は、各ライフサイクルフックにリアクティブな依存関係をオプションで渡すこともできます。これらは、基盤となる React useEffect hook に渡されます。
const [data, setData] = useState('foo');
useIonViewDidEnter(() => {
console.log('ionViewDidEnter event fired');
}, [data]);
React ライフサイクルメソッド
React のすべてのライフサイクルメソッド(`componentDidMount`、`componentWillUnmount` など)も使用できます。ただし、Ionic React はページのライフタイムを管理するため、特定のイベントが予期したとおりに発生しない場合があります。たとえば、`componentDidMount` はページが初めて表示されたときに発生しますが、ページから移動すると Ionic は DOM 内にページを保持する可能性があり、ページへの後続の訪問では `componentDidMount` が再度呼び出されない場合があります。このシナリオは、Ionic ライフサイクルメソッドが存在する主な理由であり、ネイティブフレームワークのイベントが発生しない場合でも、ビューが表示されたり終了したりしたときにロジックを呼び出す方法を提供するためです。
各ライフサイクルメソッドのガイダンス
以下は、各ライフサイクルイベントのユースケースに関するヒントです。
- `ionViewWillEnter` - `ionViewWillEnter` はビューがナビゲートされるたびに(初期化されているかどうかに関係なく)呼び出されるため、サービスからデータを読み込むのに適したメソッドです。
- `ionViewDidEnter` - データを読み込む際に `ionViewWillEnter` を使用することでパフォーマンスの問題が発生する場合は、代わりに `ionViewDidEnter` でデータ呼び出しを実行できます。ただし、このイベントはページがユーザーに表示されるまで発生しないため、ローディングインジケーターまたはスケルトン画面を使用すると、トランジションが完了した後にコンテンツが不自然に点滅することがなくなります。
- `ionViewWillLeave` - データソースからの登録解除など、クリーンアップに使用できます。`componentWillUnmount` は現在のページから移動したときに発生しない場合があるため、画面が表示されていないときにアクティブにしたくない場合は、ここにクリーンアップコードを配置します。
- `ionViewDidLeave` - このイベントが発生すると、新しいページへのトランジションが完全に完了したことがわかるため、ビューが表示されているときには通常行わないロジックはここに配置できます。
ページ間で状態を渡す
Ionic React はページのライフタイムを管理するため、前のページの状態は、ユーザーがアプリケーションをナビゲートする際に更新される場合があります。これは、React の `useEffect` や React Router の `useLocation` を使用して決定される状態に影響を与える可能性があります。たとえば、`PageA` が `useLocation` を呼び出すと、ユーザーが `PageA` から `PageB` に移動したときに `useLocation` の状態が変更されます。
開発者は、前のページが定義された状態にのみアクセスするように適切なチェックを含める必要があります。
たとえば、次のコードは、`testObject` が定義されていない場合にエラーになります。`{ state.testObject.childKey }`
代わりに、開発者は `testObject` が定義されている場合にのみ `childKey` にアクセスする必要があります。`{ state.testObject?.childKey }`