ナビゲーションイベント
React Navigationによって発信される様々なイベントをリスンして、特定のイベントを通知し、場合によってはデフォルトのアクションをオーバーライドすることができます。 `focus`、`blur`など、すべてのナビゲーターで動作するいくつかのコアイベント(下記に記載)と、特定のナビゲーターでのみ動作するナビゲーター固有のイベントがあります。
コアイベントに加えて、各ナビゲーターは独自のカスタムイベントを送信できます。たとえば、スタックナビゲーターは`transitionStart`と`transitionEnd`イベントを送信し、タブナビゲーターは`tabPress`イベントを送信します。個々のナビゲーターのドキュメントで、送信されるイベントの詳細を確認できます。
コアイベント
以下は、すべてのナビゲーターで使用可能なイベントです。
focus
このイベントは、画面がフォーカスされたときに送信されます。
ほとんどの場合、リスナーを手動で追加するよりも、useFocusEffect
フックを使用する方が適切です。使用するAPIを決定するための詳細については、このガイドを参照してください。
blur
このイベントは、画面がフォーカスから外れたときに送信されます。
state
このイベントは、ナビゲーターの状態が変更されたときに送信されます。このイベントは、イベントデータ(`event.data.state`)にナビゲーターの状態を受け取ります。
beforeRemove
このイベントは、ユーザーが画面を離れるときに送信されます。ユーザーが離れるのを防ぐことができます。
イベントのリスン
ナビゲーターからのイベントをリスンするには、複数の方法があります。イベントリスナーとして登録された各コールバックは、引数としてイベントオブジェクトを受け取ります。イベントオブジェクトにはいくつかのプロパティが含まれています。
data
- ナビゲーターによって渡されたイベントに関する追加データ。データが渡されなかった場合は`undefined`になります。target
- イベントを受け取るべき画面のルートキー。イベントが特定の画面に関連していない場合、一部のイベントでは`undefined`になる可能性があります。preventDefault
- 一部のイベントでは、イベントオブジェクトに`preventDefault`メソッドがある場合があります。このメソッドを呼び出すと、イベントによって実行されるデフォルトのアクション(`tabPress`でのタブの切り替えなど)が防止されます。アクションの防止のサポートは、`tabPress`のような特定のイベントでのみ利用可能であり、すべてのイベントで動作するわけではありません。
次のAPIを使用してイベントをリスンできます。
navigation.addListener
画面内で、`addListener`メソッドを使用して`navigation`プロップにリスナーを追加できます。`addListener`メソッドは、イベントの種類と、イベント時に呼び出されるコールバックの2つの引数を取ります。イベントの登録解除を呼び出すことができる関数を返します。
例
const unsubscribe = navigation.addListener('tabPress', (e) => {
// Prevent default action
e.preventDefault();
});
通常、関数コンポーネントでは`React.useEffect`でイベントリスナーを追加します。例えば
function Profile({ navigation }) {
React.useEffect(() => {
const unsubscribe = navigation.addListener('focus', () => {
// do something
});
return unsubscribe;
}, [navigation]);
return <ProfileContent />;
}
`unsubscribe`関数は、効果のクリーンアップ関数として返すことができます。
クラスコンポーネントの場合、`componentDidMount`ライフサイクルメソッドでイベントを追加し、`componentWillUnmount`で登録解除することができます。
class Profile extends React.Component {
componentDidMount() {
this._unsubscribe = navigation.addListener('focus', () => {
// do something
});
}
componentWillUnmount() {
this._unsubscribe();
}
render() {
// Content of the component
}
}
覚えておくべきことの1つは、`addListener`を使用して、直近のナビゲーターからのイベントのみをリスンできることです。たとえば、タブにネストされたスタック内にある画面でリスナーを追加しようとすると、`tabPress`イベントは取得されません。親ナビゲーターからのイベントをリスンする必要がある場合は、navigation.getParent
を使用して親ナビゲーターのnavigationプロップへの参照を取得し、リスナーを追加できます。
const unsubscribe = navigation
.getParent('MyTabs')
.addListener('tabPress', (e) => {
// Do something
});
ここで`'MyTabs'`は、リスンするイベントの親`Tab.Navigator`の`id`プロップに渡す値を参照します。
Screen
のlisteners
プロップ
画面内ではなく、ナビゲーターを定義したコンポーネントからリスナーを追加する場合があります。`Screen`コンポーネントの`listeners`プロップを使用して、リスナーを追加できます。`listeners`プロップは、イベント名をキーとして、リスナーコールバックを値として持つオブジェクトを取ります。
例
<Tab.Screen
name="Chat"
component={Chat}
listeners={{
tabPress: (e) => {
// Prevent default action
e.preventDefault();
},
}}
/>
リスナーを含むオブジェクトを返すコールバックを渡すこともできます。これは、`navigation`と`route`を引数として受け取ります。
例
<Tab.Screen
name="Chat"
component={Chat}
listeners={({ navigation, route }) => ({
tabPress: (e) => {
// Prevent default action
e.preventDefault();
// Do something with the `navigation` object
navigation.navigate('AnotherPlace');
},
})}
/>
ナビゲーターのscreenListeners
プロップ
ナビゲーターコンポーネントに`screenListeners`という名前のプロップを渡すことができます。ここで、このナビゲーターのすべての画面からのイベントのリスナーを指定できます。これは、画面に関係なく特定のイベントをリスンする場合、またはすべての画面に送信される`state`などの共通イベントをリスンする場合に役立ちます。
例
<Stack.Navigator
screenListeners={{
state: (e) => {
// Do something with the state
console.log('state changed', e.data);
},
}}
>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Profile" component={ProfileScreen} />
</Stack.Navigator>
`listeners`と同様に、`screenListeners`に関数も渡すことができます。関数は、各画面のnavigation
プロップとroute
プロップを受け取ります。これは、`navigation`オブジェクトにアクセスする必要がある場合に役立ちます。
<Tab.Navigator
screenListeners={({ navigation }) => ({
state: (e) => {
// Do something with the state
console.log('state changed', e.data);
// Do something with the `navigation` object
if (!navigation.canGoBack()) {
console.log("we're on the initial screen");
}
},
})}
>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Profile" component={ProfileScreen} />
</Tab.Navigator>