環境
ReactNavigation V5
目的
やりたかったこと
- ReactNavigation V5での画面遷移
- App.jsにナビゲーションの設定がしてある
- 各スクリーンは、クラスとして別ファイルに切り出し保持している
対応前のコード
ディレクトリ構成
App.js
screens
画面1.js
画面2.js
App.js
import { NavigationContainer, useNavigation } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import VID0 from './screens/画面1';
import VID1 from './screens/画面2';
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="画面1" component={画面1} />
<Stack.Screen name="画面2" component={画面2} />
</Stack.Navigator>
</NavigationContainer>
);
}
App:画面1
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
class 画面1 extends React.Component {
//スタートボタン押下時
onStartButtonPress = () => {
navigation.navigate('VID2'); //=> 注1
}
render() {
return (
<ScrollView
<Button
title='次へ'
onPress={this.onStartButtonPress}
/>
</ScrollView>
);
}
}
export default 画面1
問題
- 子スクリーンが親のNavigationを取れず、遷移できない
- 注1 の箇所 元々のReact-nativeのサンプルでは、functionであるため引数でnavigationを渡している
- しかし、今回の場合クラスであるため、引数で渡せない
対策
- useNavigation ホックを利用すれば、navigationを取ることができる
- 注意点として、このホックを使えるのは、関数内だけであるため、class中では使えない
- 以下のエラーが発生する
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
- そのため、関数でクラスをラップする
やること
-
useNavigation
をインポートする - classを関数でWrapし、関数の方をexport default する
- class のexport defaultを消す
- export defaultする関数を作る
- 関数の中で
useNavigation()
を行い、navigationを取得する - 関数はpropsを引数にとり、画面のクラスをreturnする。この時propsにnavigationを渡す
- クラスは、遷移イベント時に、this.propsからnavigationを取得する
対応後のコード
App:画面1
// ============ useNavigationを追加
import { NavigationContainer, useNavigation } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
//===ここでfunctionでクラスをWrap こっちをexport defaultする
export default function(props) {
//=== useNavigationを取得し、クラスにnavigationを渡す
const navigation = useNavigation();
return <画面1 {...props} navigation={navigation} />;
}
//=====exportしない
class 画面1 extends React.Component {
//スタートボタン押下時
onStartButtonPress = () => {
//=======関数から渡されたpropsのnavigationを取得し、利用する
const { navigation } = this.props;
navigation.navigate('VID2');
}
render() {
return (
<ScrollView
<Button
title='次へ'
onPress={this.onStartButtonPress}
/>
</ScrollView>
);
}
}