expo-router

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Expo Router Patterns

Expo Router 实践模式

Stack Navigator Configuration

Stack 导航器配置

Root Layout Setup

根布局设置

Use
screenOptions
on the Stack component to set defaults for all screens. Do NOT explicitly list every screen - routes are auto-discovered from the file structure.
tsx
// app/_layout.tsx
import { Stack } from 'expo-router';

export default function RootLayout() {
  return (
    <Stack screenOptions={{ headerShown: false }} />
  );
}
在Stack组件上使用
screenOptions
为所有屏幕设置默认配置。无需显式列出每个屏幕——路由会从文件结构中自动识别。
tsx
// app/_layout.tsx
import { Stack } from 'expo-router';

export default function RootLayout() {
  return (
    <Stack screenOptions={{ headerShown: false }} />
  );
}

Per-Screen Configuration

单屏幕配置

Individual screens configure their own options using
<Stack.Screen>
within the component file:
tsx
// app/lesson/[id].tsx
import { Stack } from 'expo-router';

export default function LessonScreen() {
  return (
    <View>
      <Stack.Screen
        options={{
          title: 'Lesson',
          headerShown: true,
          headerBackTitle: 'Back',
        }}
      />
      {/* Screen content */}
    </View>
  );
}
单个屏幕可在组件文件内通过
<Stack.Screen>
配置自身选项:
tsx
// app/lesson/[id].tsx
import { Stack } from 'expo-router';

export default function LessonScreen() {
  return (
    <View>
      <Stack.Screen
        options={{
          title: 'Lesson',
          headerShown: true,
          headerBackTitle: 'Back',
        }}
      />
      {/* 屏幕内容 */}
    </View>
  );
}

Dynamic Header Configuration

动态头部配置

Use
useNavigation
with
setOptions
for dynamic header content like buttons:
tsx
import { useNavigation } from 'expo-router';
import { useLayoutEffect } from 'react';

export default function Screen() {
  const navigation = useNavigation();

  useLayoutEffect(() => {
    navigation.setOptions({
      headerRight: () => (
        <Pressable onPress={handlePress}>
          <Ionicons name="add" size={28} />
        </Pressable>
      ),
    });
  }, [navigation]);

  return <View>{/* content */}</View>;
}
结合
useNavigation
setOptions
实现动态头部内容,比如添加按钮:
tsx
import { useNavigation } from 'expo-router';
import { useLayoutEffect } from 'react';

export default function Screen() {
  const navigation = useNavigation();

  useLayoutEffect(() => {
    navigation.setOptions({
      headerRight: () => (
        <Pressable onPress={handlePress}>
          <Ionicons name="add" size={28} />
        </Pressable>
      ),
    });
  }, [navigation]);

  return <View>{/* 内容 */}</View>;
}

Native Tabs (
expo-router/unstable-native-tabs
)

原生标签页(
expo-router/unstable-native-tabs

Native tabs provide platform-native tab bar with SF Symbols on iOS:
tsx
// app/(tabs)/_layout.tsx
import { Icon, Label, NativeTabs } from 'expo-router/unstable-native-tabs';

export default function TabLayout() {
  return (
    <NativeTabs>
      <NativeTabs.Trigger name="index" options={{ title: 'Home' }}>
        <Icon sf="house.fill" drawable="custom_android_drawable" />
        <Label>Home</Label>
      </NativeTabs.Trigger>
    </NativeTabs>
  );
}
原生标签页提供平台原生的标签栏,在iOS上支持SF Symbols:
tsx
// app/(tabs)/_layout.tsx
import { Icon, Label, NativeTabs } from 'expo-router/unstable-native-tabs';

export default function TabLayout() {
  return (
    <NativeTabs>
      <NativeTabs.Trigger name="index" options={{ title: 'Home' }}>
        <Icon sf="house.fill" drawable="custom_android_drawable" />
        <Label>Home</Label>
      </NativeTabs.Trigger>
    </NativeTabs>
  );
}

Key Principles

核心原则

  1. File-based routing: Routes are auto-discovered from the
    app/
    directory structure
  2. Minimal configuration: Only configure what you need to override
  3. Screen-level options: Screens configure their own headers/options using
    <Stack.Screen>
    within the component
  4. Layout files:
    _layout.tsx
    files define navigation structure for their directory
  5. Route groups: Parentheses like
    (tabs)
    create route groups without affecting the URL path
  1. 基于文件的路由:路由从
    app/
    目录结构中自动识别
  2. 最小化配置:仅配置需要覆盖的内容
  3. 屏幕级选项:屏幕通过组件内的
    <Stack.Screen>
    配置自身的头部/选项
  4. 布局文件
    _layout.tsx
    文件为其所在目录定义导航结构
  5. 路由分组:使用括号如
    (tabs)
    创建路由分组,不会影响URL路径

Common Mistakes to Avoid

需避免的常见错误

  • Don't list every screen explicitly in Stack - they're auto-discovered
  • Don't use
    screenOptions
    for route-specific settings - use
    <Stack.Screen>
    in the route file
  • Don't nest navigators deeply - use file-based routing for cleaner structure
  • 不要在Stack中显式列出每个屏幕——它们会被自动识别
  • 不要使用
    screenOptions
    配置路由特定设置——应在路由文件中使用
    <Stack.Screen>
  • 不要过度嵌套导航器——使用基于文件的路由实现更清晰的结构