名称: react-native-web-navigation 用户可调用: false 描述: 用于在React Native Web项目中实现导航。提供React Navigation、深度链接和Web特定路由的模式。 允许工具:
- 读取
- 写入
- 编辑
- Bash
- Grep
- Glob
React Native Web - 导航
使用React Navigation的React Native Web导航模式,支持原生和Web平台,具有统一的API。
关键概念
React Navigation
React Navigation是React Native和React Native Web的标准导航库:
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
const Stack = createNativeStackNavigator();
export function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
类型安全导航
为类型安全定义导航类型:
import type { NativeStackScreenProps } from '@react-navigation/native-stack';
type RootStackParamList = {
Home: undefined;
Details: { id: string; title: string };
Profile: { userId: string };
};
type HomeProps = NativeStackScreenProps<RootStackParamList, 'Home'>;
type DetailsProps = NativeStackScreenProps<RootStackParamList, 'Details'>;
function HomeScreen({ navigation }: HomeProps) {
return (
<Button
title="转到详情"
onPress={() => navigation.navigate('Details', { id: '123', title: '项目' })}
/>
);
}
Web URLs
React Navigation自动处理Web上的URL:
import { LinkingOptions } from '@react-navigation/native';
const linking: LinkingOptions<RootStackParamList> = {
prefixes: ['https://myapp.com', 'myapp://'],
config: {
screens: {
Home: '',
Details: 'details/:id',
Profile: 'profile/:userId',
},
},
};
<NavigationContainer linking={linking}>
{/* 导航器 */}
</NavigationContainer>
最佳实践
Stack Navigator
✅ 用于屏幕到屏幕导航:
import { createNativeStackNavigator } from '@react-navigation/native-stack';
const Stack = createNativeStackNavigator<RootStackParamList>();
function RootNavigator() {
return (
<Stack.Navigator
screenOptions={{
headerShown: true,
headerStyle: {
backgroundColor: '#007AFF',
},
headerTintColor: '#fff',
}}
>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ title: '主页' }}
/>
<Stack.Screen
name="Details"
component={DetailsScreen}
options={({ route }) => ({ title: route.params.title })}
/>
</Stack.Navigator>
);
}
Tab Navigator
✅ 用于主要应用部分:
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { Ionicons } from '@expo/vector-icons';
const Tab = createBottomTabNavigator<TabParamList>();
function TabNavigator() {
return (
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
const iconName = route.name === 'Home' ? 'home' : 'person';
return <Ionicons name={iconName} size={size} color={color} />;
},
tabBarActiveTintColor: '#007AFF',
tabBarInactiveTintColor: 'gray',
})}
>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Profile" component={ProfileScreen} />
</Tab.Navigator>
);
}
Drawer Navigator (Web)
✅ 用于Web上的侧边栏导航:
import { createDrawerNavigator } from '@react-navigation/drawer';
import { useWindowDimensions } from 'react-native';
const Drawer = createDrawerNavigator();
function DrawerNavigator() {
const { width } = useWindowDimensions();
const isLargeScreen = width >= 768;
return (
<Drawer.Navigator
screenOptions={{
drawerType: isLargeScreen ? 'permanent' : 'front',
drawerStyle: {
width: 240,
},
}}
>
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Settings" component={SettingsScreen} />
</Drawer.Navigator>
);
}
示例
完整导航设置
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
type RootStackParamList = {
Tabs: undefined;
Details: { id: string };
Modal: undefined;
};
type TabParamList = {
Home: undefined;
Search: undefined;
Profile: undefined;
};
const Stack = createNativeStackNavigator<RootStackParamList>();
const Tab = createBottomTabNavigator<TabParamList>();
function TabNavigator() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Search" component={SearchScreen} />
<Tab.Screen name="Profile" component={ProfileScreen} />
</Tab.Navigator>
);
}
export function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Tabs"
component={TabNavigator}
options={{ headerShown: false }}
/>
<Stack.Screen name="Details" component={DetailsScreen} />
<Stack.Screen
name="Modal"
component={ModalScreen}
options={{ presentation: 'modal' }}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
导航与钩子
import { useNavigation, useRoute } from '@react-navigation/native';
import type { NativeStackNavigationProp } from '@react-navigation/native-stack';
import type { RouteProp } from '@react-navigation/native';
type DetailsScreenNavigationProp = NativeStackNavigationProp<
RootStackParamList,
'Details'
>;
type DetailsScreenRouteProp = RouteProp<RootStackParamList, 'Details'>;
function DetailsScreen() {
const navigation = useNavigation<DetailsScreenNavigationProp>();
const route = useRoute<DetailsScreenRouteProp>();
const { id, title } = route.params;
return (
<View>
<Text>{title}</Text>
<Button title="返回" onPress={() => navigation.goBack()} />
<Button
title="转到个人资料"
onPress={() => navigation.navigate('Profile', { userId: id })}
/>
</View>
);
}
深度链接配置
import { LinkingOptions } from '@react-navigation/native';
const linking: LinkingOptions<RootStackParamList> = {
prefixes: ['https://myapp.com', 'myapp://'],
config: {
screens: {
Tabs: {
screens: {
Home: '',
Search: 'search',
Profile: 'profile',
},
},
Details: 'details/:id',
Modal: 'modal',
},
},
};
export function App() {
return (
<NavigationContainer linking={linking} fallback={<LoadingScreen />}>
{/* 导航器 */}
</NavigationContainer>
);
}
常见模式
受保护路由
import { useAuth } from './auth-context';
function RootNavigator() {
const { isAuthenticated } = useAuth();
return (
<Stack.Navigator>
{isAuthenticated ? (
<>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Profile" component={ProfileScreen} />
</>
) : (
<>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Register" component={RegisterScreen} />
</>
)}
</Stack.Navigator>
);
}
导航守卫
import { useNavigation } from '@react-navigation/native';
import { useEffect } from 'react';
function ProtectedScreen() {
const navigation = useNavigation();
const { isAuthenticated } = useAuth();
useEffect(() => {
if (!isAuthenticated) {
navigation.navigate('Login');
}
}, [isAuthenticated, navigation]);
if (!isAuthenticated) {
return null;
}
return <View>{/* 受保护内容 */}</View>;
}
程序化导航
import { createNavigationContainerRef } from '@react-navigation/native';
// 在组件外部创建引用
export const navigationRef = createNavigationContainerRef<RootStackParamList>();
// 在应用组件中使用
export function App() {
return (
<NavigationContainer ref={navigationRef}>
{/* 导航器 */}
</NavigationContainer>
);
}
// 从任何地方导航
export function navigateToDetails(id: string) {
if (navigationRef.isReady()) {
navigationRef.navigate('Details', { id });
}
}
反模式
❌ 不要直接使用React Router(使用React Navigation):
// 坏 - React Router仅适用于Web
import { BrowserRouter, Route } from 'react-router-dom';
// 好 - React Navigation适用于所有平台
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
❌ 不要手动传递导航属性:
// 坏
<ChildComponent navigation={navigation} />
// 好 - 使用useNavigation钩子
function ChildComponent() {
const navigation = useNavigation();
// ...
}
❌ 不要在Redux/Context中存储导航状态:
// 坏 - 导航状态应由React Navigation管理
const [currentScreen, setCurrentScreen] = useState('Home');
// 好 - 让React Navigation管理状态
// 如果需要响应变化,使用导航监听器
相关技能
- react-native-web-core: React Native Web核心概念
- react-native-web-styling: 导航组件的样式设计
- react-native-web-testing: 导航流程的测试