3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

通知からアプリを開いたときに任意の画面へ遷移する

Posted at

はじめに

タイトルままです。
ReactNativeで通知からアプリを開いたときに、
通知の種類に合わせて任意の画面を表示する方法について紹介します。

説明しないこと

  • react-navigationの基本的な使い方
  • react-native-push-notificationの基本的な使い方

使用ライブラリ

  • 通知用
    • @react-native-community/push-notification-ios:^1.8.0
    • react-native-push-notification:^7.4.0
  • タブ用
    • @react-navigation/native:^5.9.4
    • react-native-reanimated:^2.2.0
    • react-native-gesture-handler:^1.10.3
    • react-native-screens:^3.4.0
    • react-native-safe-area-context:^3.2.0
    • @react-native-community/masked-view:^0.1.11
    • @react-navigation/bottom-tabs:^5.11.11

コード

import React, {createRef} from 'react';
import {NavigationContainer} from '@react-navigation/native';
import PushNotification from 'react-native-push-notification';

const navigation = createRef().current;

PushNotification.configure({
  onNotification: notification => {
    navigation.navigate(notification.data.screen);
  },
});

PushNotification.popInitialNotification(initialNotification => {
  if (initialNotification) {
    navigation.navigate(initialNotification.data.screen);
  }
});

const scheduleNotification = (screenName) => {
  PushNotification.localNotificationSchedule({
    id: 1,
    title: 'title',
    message: 'message',
    date: new Date(now.setMinutes(now.getMinutes() + 1)), // 1分後
    userInfo: {
      screen: screenName,
    },
    channelId: 'CHANNEL_ID',
  });
}

...

<NavigationContainer ref={navigationRef}>
  <Tab.Navigator initialRouteName="Home">
    <Tab.Screen name="Home" component={HomeScreen} />
    <Tab.Screen name="Tab1" component={Tab1Screen} />
    <Tab.Screen name="Tab2" component={Tab2Screen} />
    <Tab.Screen name="Tab3" component={Tab3Screen} />
    <Tab.Screen name="Tab4" component={Tab4Screen} />
  </Tab.Navigator>
</NavigationContainer>

解説

const navigationRef = createRef();

...

<NavigationContainer ref={navigationRef}>
  <Tab.Navigator initialRouteName="Home">
    <Tab.Screen name="Home" component={HomeScreen} />
    <Tab.Screen name="Tab1" component={Tab1Screen} />
    ...
  </Tab.Navigator>
</NavigationContainer>

通知からアプリを開いたときの処理は、
後述のPushNotification.configureで設定するのですが、
react-native-push-notificationのドキュメントでは、
Must be outside of any component LifeCycle (such as `componentDidMount`).とあり、
Reactのライフサイクルの影響で重複して設定されることがないよう、
Reactコンポーネント外で実行する必要があります。

そのため、必然的にreact-navigationの画面遷移はコンポーネント外で行うことになり、
スクリーンに渡ってくるpropsuseNavigationを使えません。

そこで、NavigationContainerにRefを渡して、navigationにアクセスする方法を取ります。

PushNotification.configure({
  onNotification: notification => {
    navigation.navigate(notification.data.screen);
  },
});

PushNotification.configureonNotificationでは、
アプリを開いている状態、もしくはアプリがバックグラウンドで起動している状態で
通知をタップした場合の設定を行うことができます。

コールバック引数のnotificationdataには、
通知設定のuserInfoパラメータに設定したデータが渡ってきます。
遷移先がReactのstateに依存するような場合には、
通知設定時に遷移先を設定することで、通知の種類に応じた画面を表示することができます。

const scheduleNotification = (screenName) => {
  PushNotification.localNotificationSchedule({
    id: 1,
    title: 'title',
    message: 'message',
    date: new Date(now.setMinutes(now.getMinutes() + 1)), // 1分後
    userInfo: {
      screen: screenName,
    },
    channelId: 'CHANNEL_ID',
  });
}

アプリが起動している状態(バックグラウンド含む)では、
PushNotification.configureで通知をタップしたときの挙動を設定できますが、
アプリが起動していない状態では、
PushNotification.popInitialNotificationを使用することで、
通知からアプリを開いたときの挙動を設定できます。

PushNotification.popInitialNotification(initialNotification => {
  if (initialNotification) {
    navigation.navigate(initialNotification.data.screen);
  }
});

initialNotificationにはPushNotification.configureonNotificationと同じく、
userInfoで渡したパラメータがdataに渡ってきます。

参考

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?