react-navigation筆記
安裝依賴
npm install react-native-gesture-handler@1.7.0 react-native-reanimated@1.12.0 react-native-screens@2.10.1 react-native-safe-area-context@3.1.7 @react-native-community/masked-view@0.1.10 @react-navigation/compat@5.2.5
@react-navigation/native@5.7.3 @react-navigation/stack@5.9.0
在根文件頂部引入,否則應(yīng)用會崩潰
import 'react-native-gesture-handler';
將整個應(yīng)用包裝在 NavigationContainer
中
import 'react-native-gesture-handler';
import * as React from 'react';
import { NavigationContainer } from '@react-navigation/native';
export default function App() {
return (
<NavigationContainer>{/* Rest of your app code */}</NavigationContainer>
);
}
安裝 @react-navigation/stack
npm install @react-navigation/stack
createStackNavigator
是一個返回一個對象(包含2個屬性 Screen
和 Navigator
)的函數(shù)。 Navigator
應(yīng)該包含子元素 Screen
,來定義路由配置溢陪。用 NavigationContainer
包裹 Navigator
// In App.js in a new project
import * as React from 'react';
import { View, Text } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
function HomeScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
);
}
function DetailsScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
</View>
);
}
const Stack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator
initialRouteName="Home"
screenOptions={{ gestureEnabled: true }}>
<Stack.Screen name="Home" component={HomeScreen} options={{ title: 'Overview' }}/>
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
配置
Screen
的必需配置屬性是 name
和 component
。在 Navigator
上配置 initialRouteName
。
component
屬性接受組件盏浇,不接受一個render函數(shù)。不要傳一個內(nèi)聯(lián)函數(shù)例如 component={() => <HomeScreen />}
芽狗,否則當父組件re-render時绢掰,你的組件將卸載和重載失去的所有state。
每個路由的配置可以放在 options
里面。相同的可以配在 Navigator
的 screenOptions
里面滴劲。
傳遞額外的props:
- (推薦)使用React Context攻晒,用context provider包裹navigator去傳數(shù)據(jù)到screens。
// Context lets us pass a value deep into the component tree
// without explicitly threading it through every component.
// Create a context for the current theme (with "light" as the default).
const ThemeContext = React.createContext('light');
class App extends React.Component {
render() {
// Use a Provider to pass the current theme to the tree below.
// Any component can read it, no matter how deep it is.
// In this example, we're passing "dark" as the current value.
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
}
// A component in the middle doesn't have to
// pass the theme down explicitly anymore.
function Toolbar() {
return (
<div>
<ThemedButton />
</div>
);
}
class ThemedButton extends React.Component {
// Assign a contextType to read the current theme context.
// React will find the closest theme Provider above and use its value.
// In this example, the current theme is "dark".
static contextType = ThemeContext;
render() {
return <Button theme={this.context} />;
}
}
- 用render callback而不是定義一個component prop班挖。默認情況下react-navigation底層做了優(yōu)化防止重復(fù)渲染鲁捏,但是使用render callback則會移除這些優(yōu)化。如果用render callback萧芙,需要確保Screen組件使用了
React.memo
或React.PureComponent
<Stack.Screen name="Home">
{props => <HomeScreen {...props} extraData={someData} />}
</Stack.Screen>
路由跳轉(zhuǎn)
import * as React from 'react';
import { Button, View, Text } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
// ... other code from the previous section
navigation
屬性會傳遞給每個在stack navigator中定義的screen component缕碎。navigation.navigate('Detail')
調(diào)用navigate方法傳入路由name,可以跳轉(zhuǎn)到對應(yīng)頁面墓毒。navigation.push('Detail')
可以做到在Detail頁面打開另一個Detail頁面句喷。navigation.goBack()
路由回退。-
回退多個頁面的方式:
navigate('Home')
回退到Home頁渔期。navigation.popToTop()
會對到首頁运吓。
function DetailsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Button
title="Go to Details... again" onPress={() => navigation.push('Details')} />
<Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
<Button title="Go back" onPress={() => navigation.goBack()} />
<Button title="Go back to first screen in stack" onPress={() => navigation.popToTop()}
/>
</View>
);
}
路由傳參
步驟:
-
navigation.navigate('RouteName', { /* params go here */ })
,推薦使用JSON格式的參數(shù)疯趟。 - 在screen組件中讀取傳入的參數(shù)
route.params
拘哨。
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => {
/* 1. Navigate to the Details route with params */
navigation.navigate('Details', {
itemId: 86,
otherParam: 'anything you want here',
});
}}
/>
</View>
);
}
function DetailsScreen({ route, navigation }) {
/* 2. Get the param */
const { itemId } = route.params;
const { otherParam } = route.params;
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Text>itemId: {JSON.stringify(itemId)}</Text>
<Text>otherParam: {JSON.stringify(otherParam)}</Text>
<Button
title="Go to Details... again"
onPress={() => navigation.push('Details', { itemId: Math.floor(Math.random() * 100) }}
/>
<Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
<Button title="Go back" onPress={() => navigation.goBack()} />
</View>
);
}
更新路由參數(shù): navigation.setParams
。
傳參回到上一個頁面: navigation.navigate('',params)
傳參到嵌套的路由器:
navigation.navigate('Account', {
screen: 'Settings',
params: { user: 'jane' },
});
配置標題欄
設(shè)置標題:(在 Screen
上設(shè)置 options
)
options={{ title: 'My home' }}
-
options={({ navigation, route }) => ({ title: route.params.name })}
信峻,options
函數(shù)的參數(shù)包括navigation
和route
倦青,我們只需用到route
- 使用
navigation.setOptions({ title:'Updated!' })
更新options
修改header樣式:(在 Screen
上設(shè)置 options
)
-
headerStyle
:參考View的樣式寫法 headerTintColor
-
headerTitleStyle
:參考Text的樣式寫法 - 注意:iOS上,status bar的文字和圖標是黑色的盹舞,詳見適配方案
復(fù)用常規(guī)options:
- 在
Stack.Navigator
上配置屬性screenOptions
自定義組件替換標題: headerTitle
(默認是展示text的Text組件)
其他options:詳見文檔
function LogoTitle() {
return (
<Image
style={{ width: 50, height: 50 }}
source={require('@expo/snack-static/react-native-logo.png')}
/>
);
}
function StackScreen() {
return (
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ headerTitle: props => <LogoTitle {...props} /> }}
/>
</Stack.Navigator>
);
}
header 按鈕
添加header按鈕
- headerRight
function StackScreen() {
return (
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{
// 在options里 this 不指向HomeScreen實例姨夹,不能調(diào)用setState或其他實例方法
headerTitle: props => <LogoTitle {...props} />,
headerRight: () => (
<Button
onPress={() => alert('This is a button!')}
title="Info"
color="#fff"
/>
),
}}
/>
</Stack.Navigator>
);
}
header與它的screen組件交互
- 定義按鈕時,在screen組件內(nèi)使用
navigation.setOptions
而不是options
屬性矾策,這樣可以獲取screen的props磷账、state、context等贾虽。
function StackScreen() {
return (
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={({ navigation, route }) => ({
headerTitle: props => <LogoTitle {...props} />,
})}
/>
</Stack.Navigator>
);
}
function HomeScreen({ navigation }) {
const [count, setCount] = React.useState(0);
React.useLayoutEffect(() => {
navigation.setOptions({
headerRight: () => (
<Button onPress={() => setCount(c => c + 1)} title="Update count" />
),
});
}, [navigation]);
return <Text>Count: {count}</Text>;
}
配置回退按鈕
-
createStackNavigator
提供平臺定制的默認回退按鈕逃糟。 headerBackTitle
-
headerTruncatedBackTitle
:文檔 -
headerBackImage
:文檔
覆蓋回退按鈕
headerRight
headerLeft
- 保留button只覆蓋
onPress
方法,可以從@react-navigation/stack
導(dǎo)出HeaderBackButton
組件分配給headerLeft
選項
嵌套導(dǎo)航器(todo)
在一個導(dǎo)航器的Screen內(nèi)渲染另一個導(dǎo)航器蓬豁。
-
Stack.Navigator
-
Home
(Tab. Navigator
)-
Feed
(Screen
) -
Messages
(Screen
)
-
-
Profile
(Screen
) -
Settings
(Screen
)
-
function Home() {
return (
<Tab.Navigator>
<Tab.Screen name="Feed" component={Feed} />
<Tab.Screen name="Messages" component={Messages} />
</Tab.Navigator>
);
}
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="Profile" component={Profile} />
<Stack.Screen name="Settings" component={Settings} />
</Stack.Navigator>
</NavigationContainer>
);
}
注意:
- 每個嵌套導(dǎo)航器保持自己的導(dǎo)航歷史
- 每個嵌套導(dǎo)航器有自己的
options
- 每個嵌套導(dǎo)航器有自己的參數(shù)
- 如果需要從父Screen傳參到子Screen绰咽,可以用React Context透傳參數(shù)給children
- 導(dǎo)航actions(比如
goBack
、navigate
)會被當前導(dǎo)航器處理地粪,如果處理不了則會冒泡(被父導(dǎo)航器)處理 - 導(dǎo)航器的特定方法在嵌套導(dǎo)航器中也可用:
- 如果需要從父導(dǎo)航器dispatch actions到嵌套的子導(dǎo)航器取募,可以使用
navigation.dispatch
- 如果需要從父導(dǎo)航器dispatch actions到嵌套的子導(dǎo)航器取募,可以使用
// 從父導(dǎo)航器dispatch actions到嵌套的子導(dǎo)航器
navigation.dispatch(DrawerActions.toggleDrawer());
{/** Drawer的openDrawer方法可以被Stack調(diào)用(navigation.openDrawer) */}
<Drawer>
<Stack />
{/** ... */}
</Drawer>
{/** Drawer的openDrawer方法不可被Stack下的其他Screen調(diào)用 */}
<Stack>
<Drawer />
{/** ... */}
</Stack>
{/** Tab可以調(diào)用Stack的方法push和replace(navigation.push、navigation.replace) */}
<Stack>
<Tab/>
{/** ... */}
</Stack>
嵌套導(dǎo)航器不接收父導(dǎo)航器的事件蟆技,如需接受父導(dǎo)航器的事件玩敏,需要使用 navigation.dangerouslyGetParent()
顯式監(jiān)聽
const unsubscribe = navigation
.dangerouslyGetParent()
.addListener('tabPress', (e) => {
// Do something
});
父導(dǎo)航器的UI渲染在子導(dǎo)航器的最頂端:
- Drawer的每一個頁面中嵌套Stack:抽屜出現(xiàn)在堆棧標題的上方
- Stack中嵌套Drawer:抽屜顯式在標題下方
- Stack的首頁中嵌套Tab:新頁面會覆蓋掉tab bar
- Tab的每一個頁面中嵌套Stack:tab bar一直顯示斗忌,再按一下tab會回到stack的頂部
在嵌套導(dǎo)航器中跳轉(zhuǎn)頁面
-
Drawer.Navigator
-
Drawer.Screen
:Home
-
Drawer.Screen
:Root
-
Stack.Screen
:Profile
-
Stack.Screen
:Settings
-
-
navigation.navigate('Root');
navigation.navigate('Root', { screen: 'Settings' });
在以前的版本中,所有配置都是靜態(tài)的旺聚,但是現(xiàn)在通過動態(tài)配置织阳,直到包含Screen的導(dǎo)航器呈現(xiàn)之前,react-navigation才知道哪些Screen可用以及在哪里可用砰粹。通常唧躲,Screen在導(dǎo)航進入之前不會渲染任何東西,因此尚未渲染的導(dǎo)航器配置不可用碱璃。這使得必須制定要導(dǎo)航到的層次結(jié)構(gòu)弄痹。這也是為什么應(yīng)該盡可能減少嵌套導(dǎo)航器以使代碼更簡單的原因。
將參數(shù)傳遞給嵌套導(dǎo)航器中Screen
// 指定params傳遞參數(shù)
navigation.navigate('Root', {
screen: 'Settings',
params: {
user: 'jane'
},
});
// 深層嵌套
navigation.navigate('Root', {
screen: 'Settings',
params: {
screen: 'Sound',
params: {
screen: 'Media',
},
},
});
渲染定義在導(dǎo)航器中的初始路由
默認情況下嵌器,在嵌套導(dǎo)航器中導(dǎo)航Screen時界酒,指定的screen會被用作初始screen,并且導(dǎo)航器上的initialRoute prop會被忽略嘴秸。
如果需渲染特定的初始路由頁面,可以設(shè)置 initial: false
庇谆。
navigation.navigate('Root', {
screen: 'Settings',
initial: false,
});
嵌套多個stack 導(dǎo)航器
當嵌套多個Stack導(dǎo)航器時岳掐,react-navigation將自動隱藏子stack導(dǎo)航器的標題,以避免重復(fù)的標題饭耳。但是根據(jù)場景不同串述,顯示子stack導(dǎo)航器的標題,而不是隱藏父stack導(dǎo)航器的標題寞肖,可能更有用纲酗。可以設(shè)置 headerShown: false
解決該問題新蟆。完整示例 極少的情況觅赊,你需要同事顯示父stack導(dǎo)航器和子stack導(dǎo)航器的標題,可以在子導(dǎo)航器上設(shè)置 headerShown: true
function Home() {
return (
<NestedStack.Navigator>
<NestedStack.Screen name="Profile" component={Profile} />
<NestedStack.Screen name="Settings" component={Settings} />
</NestedStack.Navigator>
);
}
function App() {
return (
<NavigationContainer>
<RootStack.Navigator>
<RootStack.Screen
name="Home"
component={Home}
options={{ headerShown: false }}
/>
<RootStack.Screen name="EditPost" component={EditPost} />
</RootStack.Navigator>
</NavigationContainer>
);
}
嵌套的最佳做法:建議將嵌套導(dǎo)航器減少到最小琼稻。嘗試通過盡可能少的嵌套來實現(xiàn)所需的行為吮螺。缺點如下
- 會導(dǎo)致深度嵌套的視圖層級結(jié)構(gòu),從而可能導(dǎo)致低端設(shè)備出現(xiàn)內(nèi)存和性能問題
- 嵌套相同類型的導(dǎo)航器可能會導(dǎo)致混淆的用戶體驗
- 如果嵌套過多帕翻,導(dǎo)航到嵌套頁面鸠补,配置深層鏈接等時將很難編寫代碼
導(dǎo)航生命周期
堆棧導(dǎo)航器中包含A和B兩個screen。當導(dǎo)航到A頁面時嘀掸,A的 componentDidMount
被調(diào)用紫岩,當跳轉(zhuǎn)到B時,B的 componentDidMount
被調(diào)用睬塌,但是A在stack中保持mounted泉蝌,A的 componentWillUnmount
沒有被調(diào)用歇万。
當從B回退到A時,B的 componentWillUnmmount
被調(diào)用梨与,但是A的 componentDidMount
沒有被調(diào)用堕花,因為A一直是mounted狀態(tài)。
生命周期事件文檔
focus
blur
function Profile({ navigation }) {
React.useEffect(() => {
const unsubscribe = navigation.addListener('focus', () => {
// Screen was focused
// Do something
});
return unsubscribe;
}, [navigation]);
return <ProfileContent />;
}
- 代替手動添加事件監(jiān)聽粥鞋,可以用
useFocusEffect
hook去執(zhí)行副作用缘挽,類似react的useEffect
hook。 - 使用
useIsFocused
hook:返回boolean呻粹,表示屏幕是否聚焦
import { useFocusEffect } from '@react-navigation/native';
function Profile() {
useFocusEffect(
React.useCallback(() => {
// Do something when the screen is focused
return () => {
// Do something when the screen is unfocused
// Useful for cleanup functions
};
}, [])
);
return <ProfileContent />;
}
打開全屏modal(需要嵌套導(dǎo)航器知識)
在Navigator上設(shè)置屬性 mode="modal"
壕曼,調(diào)用 navigation.navigate
打開modal
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text style={{ fontSize: 30 }}>This is the home screen!</Text>
<Button
onPress={() => navigation.navigate('MyModal')}
title="Open Modal"
/>
</View>
);
}
function DetailsScreen() {
return (
<View>
<Text>Details</Text>
</View>
);
}
function ModalScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text style={{ fontSize: 30 }}>This is a modal!</Text>
<Button onPress={() => navigation.goBack()} title="Dismiss" />
</View>
);
}
const MainStack = createStackNavigator();
const RootStack = createStackNavigator();
function MainStackScreen() {
return (
<MainStack.Navigator>
<MainStack.Screen name="Home" component={HomeScreen} />
<MainStack.Screen name="Details" component={DetailsScreen} />
</MainStack.Navigator>
);
}
function RootStackScreen() {
return (
<RootStack.Navigator mode="modal">
<RootStack.Screen
name="Main"
component={MainStackScreen}
options={{ headerShown: false }}
/>
<RootStack.Screen name="MyModal" component={ModalScreen} />
</RootStack.Navigator>
);
}
注意:
-
mode
可以設(shè)置為card
(默認)和modal
(iOS:從底部劃出,從頂部向下滑動以關(guān)閉等浊;安卓:無效) - 當調(diào)用
navigate
時腮郊,除了路由外,無需指定其他任何內(nèi)容筹燕。(react-navigation嘗試在最近的導(dǎo)航器上查找路由轧飞,然后在該位置執(zhí)行操作)
Tab Navigator(todo)
術(shù)語表
header: 屏幕頂端的矩形,包含回退按鈕和標題
Navigator
:包含子元素 Screen
撒踪。NavigationContainer是一個管理導(dǎo)航樹和包含導(dǎo)航狀態(tài)的組件过咬。這個組件必須包著所有的導(dǎo)航結(jié)構(gòu)。通常我們在app的頂部(通常在App.js里)渲染這個組件制妄。
function App() {
return (
<NavigationContainer>
<Stack.Navigator> // <---- This is a Navigator
<Stack.Screen name="Home" component={HomeScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
Screen 組件:定義路由配置的組件
被配置在路由配置里的Screen組件(被 navigation.navigate
喚起的Screen)被提供了 navigation
props掸绞,
const Stack = createStackNavigator();
const StackNavigator = (
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen} // <----
/>
<Stack.Screen
name="Details"
component={DetailsScreen} // <----
/>
</Stack.Navigator>
);
Navigation prop navigation prop文檔
dispatch
navigate
goBack
- ...
Route proproute prop文檔
params
key
name
Navigation state:結(jié)構(gòu)如下,index指向當前的路由(B)
{
key: 'StackRouterRoot',
index: 1,
routes: [
{ key: 'A', name: 'Home' },
{ key: 'B', name: 'Profile' },
]
}
Route
{
key: 'B',
name: 'Profile',
params: { id: '123' }
}
兼容性層:降低升級的代碼改動成本
- 安裝
@react-navigation/compat
:
npm install @react-navigation/native @react-navigation/compat @react-navigation/stack
- 使用
createCompatNavigatorFactory
包裹
-import { createStackNavigator } from 'react-navigation-stack';
+import { createStackNavigator } from '@react-navigation/stack';
+import { createCompatNavigatorFactory } from '@react-navigation/compat';
-const RootStack = createStackNavigator(
+const RootStack = createCompatNavigatorFactory(createStackNavigator)(
{
Home: { screen: HomeScreen },
Profile: { screen: ProfileScreen },
},
{
initialRouteName: 'Profile',
}
);
-
NavigationActions
改為從@react-navigation/compat
中導(dǎo)出
-import { NavigationActions } from 'react-navigation';
+import { NavigationActions } from '@react-navigation/compat';
-
@react-navigation/compat
導(dǎo)出的api包括:- Actions:
NavigationActions
StackActions
DrawerActions
SwitchActions
- HOCs
withNavigation
withNavigationFocus
- Navigators
createSwitchNavigator
- Compatibility helpers
-
createCompatNavigatorFactory
- 傳入一個使用v5的api的導(dǎo)航器耕捞,返回一個使用v4 api的createXNavigator
-
createCompatNavigationProp
- 傳入一個v5 的navigation
對象 和route對象衔掸,返回一個v4的navigation
對象
-
- Actions:
-
兼容層處理了:
- 使用v4的靜態(tài)配置api,俄日不是基于api的組件
- 改變了
navigation
對象上的方法名稱去適配v4 - 添加了對
screenProps
的支持(v5上被移除) - 導(dǎo)出了跟v4同名的action creators俺抽,例如
NavigationActions
敞映、StackActions
、SwitchActions
磷斧。
-
兼容層沒處理:v5動態(tài)api導(dǎo)致v4靜態(tài)api不再具有某些功能
- 不再包含navigator的props或者options驱显。意味著你要傳遞給navigator的options可能因為重大改變而不同。
- 通過在路由配置中定義path來定義舊式深層鏈接是不支持的
- 導(dǎo)航到導(dǎo)航器的工作原理不同瞳抓,我們無法導(dǎo)航到尚未渲染的導(dǎo)航器中的屏幕埃疫,并且參數(shù)不會合并到所有子屏幕。
- 某些采取一系列操作的方法例如
reset
將不再支持孩哑。 - 不導(dǎo)出
createAppContainer
栓霜,需要對容器使用v5的apiNavigationContainer
。 - 如果使用的高階api例如Redux集成横蜒、自定義路由器胳蛮、actions销凑,這些不再支持,并且你需要移除Redux集成仅炊。
-
為什么用:
- 允許使用新api寫代碼斗幼,同時使用舊api與代碼集成
- 建立在支持TypeScript的v5之上,舊代碼也可以利用類型檢查功能抚垄,對重構(gòu)有幫助
- 可以在舊組件中訪問新api蜕窿,例如
navigation.setOptions
或者一些新的hook例如useFocusEffect
。
在沒用navigation props時navigate
有時你需要從一個沒有
navigation
prop的地方觸發(fā)navigation action呆馁,比如redux middleware桐经,在這種時候,你可以從navigation容器中dispatch navigation actions浙滤。如果你想要找一種方式阴挣,從一個不需要傳
navigation
prop下去的組件里面navigate,可以用useNavigation
纺腊。當你可以拿到navigation prop或者useNavigation
時不要用這個方法畔咧,因為它的行為會有所不同,而且許多特定于屏幕的helper方法將不可用揖膜。你可以通過
ref
訪問根導(dǎo)航器對象誓沸,將其傳遞給RootNavigation
,我們稍后將使用該RootNavigation
進行導(dǎo)航次氨。
// App.js
import { NavigationContainer } from '@react-navigation/native';
import { navigationRef } from './RootNavigation';
export default function App() {
return (
<NavigationContainer ref={navigationRef}>{/* ... */}</NavigationContainer>
);
}