ionic-reactことはじめとIonicでのReactライフサイクルなど
この記事は、React Advent Calendar 2019の第一日目です。 IonicでReactが使えるようになってしばらく経ちました。まだちゃんと触ったりドキュメントを終えていなかったので、ざっと動かして調べて […]
目次
この記事は、React Advent Calendar 2019の第一日目です。
IonicでReactが使えるようになってしばらく経ちました。まだちゃんと触ったりドキュメントを終えていなかったので、ざっと動かして調べてみたまとめです。
事前準備
Node.jsのバージョンを以下のいずれか以上にしましょう。ionic startで立ち上げるテンプレートに@typescript-eslint/eslint-plugin
が入っていることがあります。
こいつがNode.jsのバージョン指定をしているため、以下のバージョン以下のNode.jsを使っているとセットアップが落ちます。
- 8.10.0以上
- 10.13.0以上
- 11.10.1以上
IonicのCLIを(記事執筆時点の)最新版にします。
$ npm i -g ionic@latest
updated 1 package in 15.206s
$ ionic -v
5.4.9
プロジェクトのセットアップ
早速プロジェクトを立ち上げます。今回はあえて対話式にしていますが、オプションをつけることで1発で立ち上げも可能です。
$ ionic start
Every great app needs a name! 😍
Please enter the full name of your app. You can change this at any time. To bypass this prompt next time, supply name,
the first argument to ionic start.
? Project name: YOUR_APP_NAME
FrameworkをReactにする
プロジェクト名を指定すると、フレームワークが選べます。ここはおそらく将来的に他のフレームワークも出てくるのでしょう。
Pick a framework! 😁
Please select the JavaScript framework to use for your new app. To bypass this prompt next time, supply a value for the
--type option.
? Framework:
Angular | https://angular.io
❯ React | https://reactjs.org
テンプレートを指定する
続いてテンプレートを指定します。blankで一から作るのも良いですが、今回はあえてconferenceでがっつり作ってあるやつを選んでみます。
Starter templates are ready-to-go Ionic apps that come packed with everything you need to build your app. To bypass this
prompt next time, supply template, the second argument to ionic start.
? Starter template:
blank | A blank starter project
sidemenu | A starting project with a side menu with navigation in the content area
tabs | A starting project with a simple tabbed interface
❯ conference | A kitchen-sink application that shows off all Ionic has to offer
ちなみにここで以下のエラーが出た場合は、Node.jsのバージョンが古いです。 Nodeのバージョンをアップデートしたのち、cd YOUR_APP_NAME && yarn
を実行してリトライしてやりましょう。
error @typescript-eslint/[email protected]: The engine "node" is incompatible with this module. Expected version "^8.10.0 || ^10.13.0 || >=11.10.1". Got "10.5.0"
error Found incompatible module.
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.
[ERROR] An error occurred while running subprocess yarn.
yarn install --non-interactive exited with exit code 1.
Re-running this command with the --verbose flag may provide more information.
こっちのメッセージが出たら準備完了です。
INFO] Next Steps:
- Go to your cloned project: cd ./YOUR_APP_NAME
- Run ionic serve within the app directory to see your app
- Build features and components: https://ion.link/scaffolding-docs
- Run your app on a hardware or virtual device: https://ion.link/running-docs
Ionic Reactアプリをローカル起動する
続いてローカル起動させてみましょう。
$ cd ./YOUR_APP_NAME
$ ionic serve
> react-scripts start
[react-scripts] Starting the development server...
わかる人にはわかるやつですが、react-scripts
が出てくるということは、Ionic Reactはcreate-react-app
を使ってセットアップされています。ちなみにドキュメントにもそう書かれていました。
localhostのURLが出てこない場合
conferenceのtemplateですが、この記事をかいている時点だと、ionic serve
でlocalhostの何番で起動したかがわからなくなっています。
> react-scripts start
[react-scripts] Starting the development server...
[react-scripts]
[react-scripts] Compiled with warnings.
[react-scripts]
[react-scripts] ./src/components/SessionListItem.tsx
[react-scripts] Line 1:25: 'useState' is defined but never used @typescript-eslint/no-unused-vars
[react-scripts] Line 2:26: 'IonAlert' is defined but never used @typescript-eslint/no-unused-vars
[react-scripts] ./src/data/connect.tsx
[react-scripts] Line 1:29: 'useEffect' is defined but never used @typescript-eslint/no-unused-vars
[react-scripts] Line 1:40: 'useState' is defined but never used @typescript-eslint/no-unused-vars
[react-scripts] Line 39:8: React Hook useMemo has a missing dependency: 'context'. Either include it or remove the dependency array. Outer scope values like 'mapDispatchToProps' aren't valid dependencies because mutating them doesn't re-render the component react-hooks/exhaustive-deps
[react-scripts] Line 44:8: React Hook useMemo has a missing dependency: 'dispatchFuncs'. Either include it or remove the dependency array react-hooks/exhaustive-deps
[react-scripts] ./src/pages/SchedulePage.tsx
[react-scripts] Line 9:25: 'addFavorite' is defined but never used @typescript-eslint/no-unused-vars
[react-scripts] Line 9:38: 'removeFavorite' is defined but never used @typescript-eslint/no-unused-vars
[react-scripts] Search for the keywords to learn more about each warning.
[react-scripts] To ignore, add // eslint-disable-next-line to the line before.
ESLintのwarningが先に出てきてしまっているという状態ですね。内容に合わせて修正すればOKではあります。
本来はIssueなりPR出したりしないとかなと思いつつ、カレンダーに間にあわせるためにとりあえずここに書いてます。後でやります。
もしURLが出てこない場合は、https://localhost:8100/tutorial
を試してみてください。自分の場合はこれでいけました。
Ionic Reactには独自のライフサイクルがある
Reactであれば通常component[Did | Will]XXX
やuseXXX
というライフサイクルメソッドを使います。Ionicの場合、これらのIonic版が用意されていますので、こちらを使うことになります。
- ionViewWillEnter コンポーネントが表示されるアニメーションがはじまる時に発火します。
- ionViewDidEnter コンポーネントが表示されるアニメーションが終了した時に発火します。
- ionViewWillLeave コンポーネントを離脱するアニメーションがはじまる時に発火します。
- ionViewDidLeave コンポーネントを離脱するアニメーションが終了した時に発火します。
from: https://ionicframework.com/jp/docs/react/lifecycle
React側で非推奨になったcomponentWillMount
的に使えそうなメソッドがあるのが目につきますね。
Tips: ionViewWillEnterはcomponentDidMount相当
ぱっと見componentWillMount
を使っちゃってるのかなと思えますが、実装をみるとcomponentDidMount
にいるっぽいです。
詳しく追いきれていませんが、Reactのライフサイクル -> Ionicのライフサイクルになるイメージでしょうか。
Ionic Reactでは、なるべくIonicのライフサイクルを利用しよう
ドキュメントにも記載されていますが、React側のライフサイクルを使うと、意図しない動きになることがある様子です。
ただし、Ionic Reactはページのライフタイムを管理するため、特定のイベントが期待どおりに発生しない場合があります。 たとえば、最初にページが表示されたときは
componentDidMount
が起動しますが、ページから移動した時にIonicはページをDOMツリーに保持しているため、その後の当該ページへのアクセスではcomponentDidMount
を再度呼び出さない場合があります。
Reactのライフサイクルも使えるが、なるべくIonic側のライフサイクルにのる必要がありそうです。