Skip to content

页面传参 / 返回上一页

第五部分:路由导航(页面跳转)

在 React Native 应用中,页面之间的参数传递和返回操作是常见的需求。本文将详细介绍如何在 React Navigation 中实现页面传参和返回上一页的操作。

1. 页面传参

基本参数传递

在导航时,可以通过 navigation.navigate() 方法传递参数:

jsx
// HomeScreen.js
import React from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';

export default function HomeScreen({ navigation }) {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>首页</Text>
      <Button
        title="跳转到详情页(带参数)"
        onPress={() => navigation.navigate('Details', {
          id: 1,
          title: '产品详情',
          price: 99.99,
          description: '这是一个测试产品',
        })}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  title: {
    fontSize: 24,
    marginBottom: 20,
  },
});

接收参数

在目标屏幕中,可以通过 route.params 接收参数:

jsx
// DetailsScreen.js
import React from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';

export default function DetailsScreen({ navigation, route }) {
  const { id, title, price, description } = route.params || {};

  return (
    <View style={styles.container}>
      <Text style={styles.title}>{title || '详情页'}</Text>
      <Text style={styles.info}>ID: {id}</Text>
      <Text style={styles.info}>价格: ¥{price}</Text>
      <Text style={styles.info}>描述: {description}</Text>
      <Button
        title="返回首页"
        onPress={() => navigation.goBack()}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    gap: 20,
  },
  title: {
    fontSize: 24,
    marginBottom: 20,
  },
  info: {
    fontSize: 16,
  },
});

可选参数

可以通过解构赋值和默认值处理可选参数:

jsx
// DetailsScreen.js
import React from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';

export default function DetailsScreen({ navigation, route }) {
  const { id, title = '默认标题', price = 0, description = '暂无描述' } = route.params || {};

  return (
    <View style={styles.container}>
      <Text style={styles.title}>{title}</Text>
      <Text style={styles.info}>ID: {id}</Text>
      <Text style={styles.info}>价格: ¥{price}</Text>
      <Text style={styles.info}>描述: {description}</Text>
      <Button
        title="返回首页"
        onPress={() => navigation.goBack()}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    gap: 20,
  },
  title: {
    fontSize: 24,
    marginBottom: 20,
  },
  info: {
    fontSize: 16,
  },
});

2. 返回上一页

基本返回

使用 navigation.goBack() 方法返回上一页:

jsx
// DetailsScreen.js
import React from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';

export default function DetailsScreen({ navigation }) {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>详情页</Text>
      <Button
        title="返回上一页"
        onPress={() => navigation.goBack()}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  title: {
    fontSize: 24,
    marginBottom: 20,
  },
});

返回指定页面

使用 navigation.navigate() 方法返回指定页面:

jsx
// DetailsScreen.js
import React from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';

export default function DetailsScreen({ navigation }) {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>详情页</Text>
      <Button
        title="返回首页"
        onPress={() => navigation.navigate('Home')}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  title: {
    fontSize: 24,
    marginBottom: 20,
  },
});

返回导航栈顶部

使用 navigation.popToTop() 方法返回导航栈的顶部页面:

jsx
// DetailsScreen.js
import React from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';

export default function DetailsScreen({ navigation }) {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>详情页</Text>
      <Button
        title="返回首页(顶部)"
        onPress={() => navigation.popToTop()}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  title: {
    fontSize: 24,
    marginBottom: 20,
  },
});

3. 返回时传递参数

基本用法

可以在返回时通过 navigation.navigate()navigation.goBack() 传递参数:

jsx
// DetailsScreen.js
import React from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';

export default function DetailsScreen({ navigation, route }) {
  const handleReturnWithParams = () => {
    // 方法 1: 使用 navigate
    navigation.navigate('Home', { fromDetails: true, selectedId: route.params?.id });
    
    // 方法 2: 使用 goBack 配合 setParams
    // navigation.setParams({ returned: true });
    // navigation.goBack();
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>详情页</Text>
      <Button
        title="返回首页(带参数)"
        onPress={handleReturnWithParams}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  title: {
    fontSize: 24,
    marginBottom: 20,
  },
});

使用回调函数

可以使用回调函数在返回时传递参数:

jsx
// HomeScreen.js
import React, { useState } from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';

export default function HomeScreen({ navigation }) {
  const [returnedData, setReturnedData] = useState(null);

  const handleNavigateToDetails = () => {
    // 导航到详情页并传递回调函数
    navigation.navigate('Details', {
      onReturn: (data) => {
        setReturnedData(data);
      },
    });
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>首页</Text>
      {returnedData && (
        <Text style={styles.returnedData}>
          从详情页返回的数据: {JSON.stringify(returnedData)}
        </Text>
      )}
      <Button
        title="跳转到详情页"
        onPress={handleNavigateToDetails}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    gap: 20,
  },
  title: {
    fontSize: 24,
    marginBottom: 20,
  },
  returnedData: {
    fontSize: 16,
    color: '#4CAF50',
  },
});
jsx
// DetailsScreen.js
import React from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';

export default function DetailsScreen({ navigation, route }) {
  const { onReturn } = route.params || {};

  const handleReturnWithData = () => {
    // 调用回调函数传递数据
    if (onReturn) {
      onReturn({ selectedId: 1, message: '操作成功' });
    }
    navigation.goBack();
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>详情页</Text>
      <Button
        title="返回首页(带数据)"
        onPress={handleReturnWithData}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  title: {
    fontSize: 24,
    marginBottom: 20,
  },
});

4. 高级参数传递

嵌套导航中的参数传递

在嵌套导航中,可以使用 navigation.navigate() 方法传递参数到子导航器:

jsx
// 从首页导航到详情页(嵌套导航)
navigation.navigate('HomeStack', {
  screen: 'Details',
  params: {
    id: 1,
    title: '产品详情',
  },
});

深层链接参数

在深层链接中,可以通过 URL 参数传递数据:

jsx
// App.js
import React from 'react';
import { NavigationContainer, useLinking } from '@react-navigation/native';
import AppStackNavigator from './navigation/StackNavigator';

function App() {
  const { getInitialState } = useLinking({
    prefixes: ['myapp://', 'https://myapp.com'],
    config: {
      screens: {
        Home: '',
        Details: 'details/:id',
      },
    },
  });

  // ... 其他代码

  return (
    <NavigationContainer initialState={initialState}>
      <AppStackNavigator />
    </NavigationContainer>
  );
}

export default App;
jsx
// DetailsScreen.js
import React from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';

export default function DetailsScreen({ navigation, route }) {
  // 从 URL 参数中获取 id
  const { id } = route.params || {};

  return (
    <View style={styles.container}>
      <Text style={styles.title}>详情页</Text>
      <Text style={styles.info}>ID: {id}</Text>
      <Button
        title="返回首页"
        onPress={() => navigation.goBack()}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  title: {
    fontSize: 24,
    marginBottom: 20,
  },
  info: {
    fontSize: 16,
  },
});

状态管理中的参数

对于复杂的参数传递,可以使用状态管理库(如 Redux 或 Context API):

jsx
// contexts/AppContext.js
import React, { createContext, useState, useContext } from 'react';

const AppContext = createContext();

export const AppProvider = ({ children }) => {
  const [selectedItem, setSelectedItem] = useState(null);

  return (
    <AppContext.Provider value={{ selectedItem, setSelectedItem }}>
      {children}
    </AppContext.Provider>
  );
};

export const useApp = () => {
  const context = useContext(AppContext);
  if (!context) {
    throw new Error('useApp must be used within an AppProvider');
  }
  return context;
};
jsx
// HomeScreen.js
import React from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
import { useApp } from './contexts/AppContext';

export default function HomeScreen({ navigation }) {
  const { setSelectedItem } = useApp();

  const handleNavigateToDetails = () => {
    const item = { id: 1, title: '产品详情' };
    setSelectedItem(item);
    navigation.navigate('Details');
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>首页</Text>
      <Button
        title="跳转到详情页"
        onPress={handleNavigateToDetails}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  title: {
    fontSize: 24,
    marginBottom: 20,
  },
});
jsx
// DetailsScreen.js
import React from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
import { useApp } from './contexts/AppContext';

export default function DetailsScreen({ navigation }) {
  const { selectedItem } = useApp();

  return (
    <View style={styles.container}>
      <Text style={styles.title}>{selectedItem?.title || '详情页'}</Text>
      <Text style={styles.info}>ID: {selectedItem?.id}</Text>
      <Button
        title="返回首页"
        onPress={() => navigation.goBack()}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  title: {
    fontSize: 24,
    marginBottom: 20,
  },
  info: {
    fontSize: 16,
  },
});

5. 常见问题与解决方案

问题 1:参数传递失败

问题:无法在页面之间传递参数。

解决方案

  • 确保使用正确的导航方法:navigation.navigate('ScreenName', { params })
  • 确保在目标屏幕中正确获取参数:const { route } = props; const { params } = route;
  • 检查参数是否为可序列化的值(避免传递函数或循环引用)

问题 2:返回时参数丢失

问题:返回上一页时传递的参数丢失。

解决方案

  • 使用回调函数传递参数
  • 使用状态管理库存储参数
  • 使用 navigation.setParams() 方法更新参数

问题 3:嵌套导航参数传递

问题:在嵌套导航中无法传递参数。

解决方案

  • 使用正确的嵌套导航语法:navigation.navigate('StackName', { screen: 'ScreenName', params: { ... } })
  • 确保子导航器正确接收参数

问题 4:深层链接参数解析

问题:深层链接中的参数无法正确解析。

解决方案

  • 确保 useLinking 配置正确
  • 检查 URL 格式是否符合配置
  • 使用 route.params 正确获取参数

6. 最佳实践

1. 类型定义

为导航参数添加类型定义,提高代码的可维护性:

typescript
// navigation/types.ts
export type RootStackParamList = {
  Home: {
    fromDetails?: boolean;
    selectedId?: number;
  } | undefined;
  Details: {
    id: number;
    title: string;
    price?: number;
    description?: string;
    onReturn?: (data: { selectedId: number; message: string }) => void;
  };
};

2. 参数验证

对传递的参数进行验证,确保应用的稳定性:

jsx
// DetailsScreen.js
import React from 'react';
import { View, Text, Button, StyleSheet, Alert } from 'react-native';

export default function DetailsScreen({ navigation, route }) {
  const { id, title, price } = route.params || {};

  // 验证参数
  if (!id || !title) {
    Alert.alert('错误', '缺少必要参数');
    navigation.goBack();
    return null;
  }

  return (
    <View style={styles.container}>
      <Text style={styles.title}>{title}</Text>
      <Text style={styles.info}>ID: {id}</Text>
      <Text style={styles.info}>价格: ¥{price || 0}</Text>
      <Button
        title="返回首页"
        onPress={() => navigation.goBack()}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  title: {
    fontSize: 24,
    marginBottom: 20,
  },
  info: {
    fontSize: 16,
  },
});

3. 合理使用参数传递方式

  • 对于简单参数,使用 navigation.navigate() 直接传递
  • 对于复杂参数或需要在多个页面共享的参数,使用状态管理库
  • 对于返回时需要传递的数据,使用回调函数

4. 清理参数

在不需要参数时,及时清理参数,避免内存泄漏:

jsx
// DetailsScreen.js
import React, { useEffect } from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';

export default function DetailsScreen({ navigation, route }) {
  const { id, title } = route.params || {};

  // 组件卸载时清理参数
  useEffect(() => {
    return () => {
      navigation.setParams({});
    };
  }, [navigation]);

  return (
    <View style={styles.container}>
      <Text style={styles.title}>{title}</Text>
      <Text style={styles.info}>ID: {id}</Text>
      <Button
        title="返回首页"
        onPress={() => navigation.goBack()}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  title: {
    fontSize: 24,
    marginBottom: 20,
  },
  info: {
    fontSize: 16,
  },
});

7. 总结

页面传参和返回操作是 React Navigation 中的重要功能。通过本文的学习,你应该掌握了以下内容:

  1. 基本参数传递方法
  2. 参数接收和处理
  3. 返回上一页的方法
  4. 返回时传递参数
  5. 高级参数传递技巧
  6. 常见问题的解决方案
  7. 最佳实践

在实际开发中,合理使用这些方法,可以创建出流畅、直观的页面导航体验,提升应用的用户体验。

© 2026 编程马·菜鸟教程 版权所有