Honmushi blog
React Navigationで画面遷移時に処理を実行する2019/07/12

React Navigationで画面遷移時に処理を実行する

Expoでアプリを作ってますが、ReactNavigationの利用時に難しかったことをメモしておきます。 マウント時でも更新時でもなく、フォーカス時に処理を行いたいというものです。

結論「‘didFocus’ event listener」を使ってイベントリスナーを登録することで実装できました。 Reactのライフサイクルも理解出来たのでとても良い勉強になったと思います。

概要

  • やりたいこと
  • 「createBottomTabNavigator」のオプションでは実現できず
  • 「‘didFocus’ event listener」を使ってイベントを登録することで実装
  • 別のやり方もある
  • Reactのライフサイクルについて

やりたいこと

Reactのライフサイクルとしては、マウント時そして更新時にそれぞれrenderによって描写が行われます。
https://ja.reactjs.org/docs/react-component.html

マウント時は画面を開いた際に処理され画面を破棄するまでのこります。更新についてはsetStateを行うことで発生します。

今回は、「すでにコンポーネントがマウント済みの状態で、他の画面から遷移して再度表示した際に画面を更新したい」というものでした。

例えば、一覧画面がありその各要素を更新・削除・追加した際とかです。各要素を一覧画面のstateにしておけば要素を編集した際にrenderが行われます。今回は編集画面を別のScreenにしていたので、編集画面で要素を更新・削除しても、一覧画面では編集前の要素が表示されたままでした。

画面に遷移した際、すなわちフォーカスされた時をどうやって実装するのかわからなかったので調べました。

「createBottomTabNavigator」のオプションでは実現できず

下部のタブを作成する際の「createBottomTabNavigator」にて、configとして以下の設定ができますが、こちらをtrueにしても意図通りの挙動にはなりませんでした。

resetOnBlur - Reset the state of any nested navigators when switching away from a screen. Defaults to false.

説明にもありますが画面から離れた際、すなわちフォーカスが外れた際にのみstateのリセットが行われます。タブナビゲーションで遷移していればこれで良さそうでしたが、今回は同一タブ内でスタックしているscreen間での遷移でしたので、意図通りに更新されませんでした。

「‘didFocus’ event listener」を使ってイベントを登録することで実装

https://reactnavigation.org/docs/en/function-after-focusing-screen.html
上記のページにズバリやりたいことがありました。こちらを参考にすることで意図した挙動を実現できました。

マウント時に、didFocusにイベントリスナーを追加しておくことで、フォーカスされた際に処理を実行できます。この中に、データの再取得とsetStateを実行するようにしました。

エクスポートする際にwithNavigationを追加すること。アンマウント時にイベントリスナーを開放することも忘れないようにしましょう。

import { withNavigation } from "react-navigation";

~~~~~~
  componentDidMount() {
    const { navigation } = this.props;
    this.focusListener = navigation.addListener("didFocus", () => {
      // The screen is focused
      // Call any action
    });
  }

  componentWillUnmount() {
    // Remove the event listener
    this.focusListener.remove();
  }
~~~~~~

export default withNavigation(TabScreen);

別のやり方もある

同じページに記載されているのですが、「withNavigationFocus」と「isFocused」を利用することでも実現ができる?ように書かれていました。

ただ、このドキュメントの例では「componentDidUpdate」の中で処理が行われているため、更新時にフォーカスが移ってきたかどうかを判定するものと判断し、利用しませんでした。

Reactのライフサイクルについて

基本的に以下のドキュメントに書いてあることですが、この機会にまとめとして記録しておきます。
https://ja.reactjs.org/docs/react-component.html

マウント

コンポーネントのマウントの際は以下の順に実行されます。

constructor()
static getDerivedStateFromProps()
render()
componentDidMount()

使ってはいけないもの

UNSAFE_componentWillMount()

更新

更新はpropsやstateの変更によって発生する。コンポーネントが再レンダーされるときに、これらのメソッドが次の順序で呼び出されます。

static getDerivedStateFromProps()
shouldComponentUpdate()
render()
getSnapshotBeforeUpdate()
componentDidUpdate()

使ってはいけないもの

UNSAFE_componentWillUpdate()
UNSAFE_componentWillReceiveProps()

アンマウント

コンポーネントが DOM から削除されるときに呼び出されます。

componentWillUnmount()

おわりに

ReactNavigationを使うことでタブ構造やスタック構造によるページを簡単に作成することが出来とても快適です。 Expoを使ったアプリでもWebの様に利用できるため、知識を流用しやすいです。

URLとかメタタグ何かのSEO処理はちょっとややこしそうですが、アプリであればそれほど考えることもないのでさくっと実装ができます。

タブナビゲーションやスタックナビゲーションなど、それらしい形になるものが一通り揃っているので、とりあえずデフォルトのアプリでも触ってみると理解が深まって良いと思います。最初はややこしいと思いましたが、ScreenとStackとTabナビゲーションの関係をドキュメント見ながら理解するとすぐに使いこなせるようになりますよ。

  • このエントリーをはてなブックマークに追加