背景
- react-navigationを使っていてページ遷移を契機に処理を実行したい
- 例えば特定のページだけAndroidのバックボタンを制御したいようなときに、ページ遷移ではcomponentWillUnmount等通らないので解除するタイミングがない
- 次のページのcomponentWillMountで解除してもいいが戻られた時に制御が外れてしまう
対応サンプル
- react-navigationの機能でページ遷移を検知することができた
index.android.js
import React, { Component } from 'react';
import { AppRegistry } from 'react-native';
import AppNavigator, { disabledBackScreens } from './app/navigators/AppNavigator';
import { disabledAndroidBack, abledAndroidBack } from './app/utils/Util';
class ReactNativeSample extends Component {
render() {
// onNavigationStateChangeに渡す関数がページ遷移の度に呼ばれる
return <AppNavigator onNavigationStateChange={this.onNavigationStateChange} />;
}
// 引数のサンプルは後述
onNavigationStateChange(prevState, currentState, action) {
// routesは遷移履歴の配列
const routes = currentState.routes;
// 現在の画面は配列の最後、routeNameで画面名がとれる
const currentRouteName = routes[routes.length - 1].routeName;
// ここの例では戻るを無効にしたい画面か判断しそれぞれ処理を呼んでいる
disabledBackScreens.includes(currentRouteName) ? disabledAndroidBack() : abledAndroidBack();
}
}
AppRegistry.registerComponent('ReactNativeSample', () => ReactNativeSample);
app/navigators/AppNavigator.js
import { StackNavigator } from 'react-navigation';
import SampleAScreen from '../containers/SampleAScreen';
import SampleBScreen from '../containers/SampleBScreen';
import SampleCScreen from '../containers/SampleCScreen';
import SampleDScreen from '../containers/SampleDScreen';
import SampleEScreen from '../containers/SampleEScreen';
const AppNavigator = StackNavigator({
SampleA: { screen: SampleAScreen },
SampleB: { screen: SampleBScreen },
SampleC: { screen: SampleCScreen },
SampleD: { screen: SampleDScreen },
SampleE: { screen: SampleEScreen },
});
export const disabledBackScreens = ['SampleB', 'SampleD'];
export default AppNavigator;
app/utils/Util.js
import { BackHandler } from 'react-native'
// trueを返すとバックボタンを押した時のデフォルトの動きをキャンセルしてくれる
const androidBackHandler = () => true
export const disabledAndroidBack = () =>{
BackHandler.addEventListener('hardwareBackPress', androidBackHandler)
}
export const abledAndroidBack = () =>{
// 第二引数はaddEventListenerした時の第二引数と同じものでないとダメ
BackHandler.removeEventListener('hardwareBackPress', androidBackHandler)
}
まとめ
- ページ遷移の度に処理をかませることが出来るので何かと便利そう