React Native中如何将扫码得到的条码数据传递到其他屏幕
React Native Stack导航扫码页返回首页传值方案
直接修改三个对应文件即可,核心是避免重复创建首页实例,同时给首页加聚焦监听接收参数,不要依赖组件首次挂载的生命周期取路由参数。
第一步:确认App.js导航栈基础配置
确保Stack导航没有多余配置,两个页面正常注册即可,参考代码:
// App.js import { NavigationContainer } from '@react-navigation/native'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; import Home from './Home'; import Scanner from './Scanner'; const Stack = createNativeStackNavigator(); export default function App() { return ( <NavigationContainer> <Stack.Navigator initialRouteName="Home"> <Stack.Screen name="Home" component={Home} /> <Stack.Screen name="Scanner" component={Scanner} /> </Stack.Navigator> </NavigationContainer> ); }
第二步:修改Home.js,增加参数接收逻辑
注意从子页返回时首页不会重新挂载,不要只在组件首次加载的useEffect里取参数,要加页面聚焦监听,参考代码:
// Home.js import { useState } from 'react'; import { View, Text, Button, StyleSheet } from 'react-native'; import { useFocusEffect, useNavigation } from '@react-navigation/native'; export default function Home() { const navigation = useNavigation(); // 本地state存储扫码结果用于页面渲染 const [scanResult, setScanResult] = useState({ barcodeContent: '', scanTime: '' }); // 页面每次获得焦点时触发,接收回传的扫码参数 useFocusEffect(() => { const routes = navigation.getState()?.routes; const homeRoute = routes?.find(route => route.name === 'Home'); const params = homeRoute?.params; // 有有效扫码参数时更新展示内容 if (params?.barcodeContent && params?.scanTime) { setScanResult({ barcodeContent: params.barcodeContent, scanTime: params.scanTime }); // 取完参数清空路由缓存,避免重复展示旧结果 navigation.setParams({ barcodeContent: undefined, scanTime: undefined }) } }); return ( <View style={styles.container}> <Text style={styles.title}>扫码结果展示</Text> {scanResult.barcodeContent ? ( <View style={styles.resultBox}> <Text>条码内容:{scanResult.barcodeContent}</Text> <Text>扫码时间:{scanResult.scanTime}</Text> </View> ) : ( <Text style={styles.tip}>暂无扫码记录</Text> )} <Button title="开始扫码" onPress={() => navigation.navigate('Scanner')} /> </View> ) } const styles = StyleSheet.create({ container: { flex: 1, padding: 20, paddingTop: 80 }, title: { fontSize: 20, fontWeight: 'bold', marginBottom: 30 }, resultBox: { padding: 15, backgroundColor: '#f0f0f0', borderRadius: 8, marginBottom: 30, gap: 10 }, tip: { color: '#666', marginBottom: 30 } })
第三步:修改Scanner.js,确认扫码后回传参数再返回
不要用push或者重复navigate创建新的首页实例,用官方支持的回传参数方式跳转,参考代码:
// Scanner.js import { useState, useEffect } from 'react'; import { View, Text, Button, StyleSheet } from 'react-native'; import { BarCodeScanner } from 'expo-barcode-scanner'; import { useNavigation } from '@react-navigation/native'; export default function Scanner() { const navigation = useNavigation(); const [hasPermission, setHasPermission] = useState(null); const [scannedData, setScannedData] = useState(null); const [scanTime, setScanTime] = useState(''); // 相机权限申请 useEffect(() => { const getPermission = async () => { const { status } = await BarCodeScanner.requestPermissionsAsync(); setHasPermission(status === 'granted'); }; getPermission(); }, []); // 条码识别回调 const handleBarCodeScanned = ({ data }) => { // 加判断避免连续触发重复扫码 if (scannedData) return; setScannedData(data); // 拼接格式化扫码时间 const now = new Date(); const timeStr = `${now.getFullYear()}-${String(now.getMonth()+1).padStart(2,'0')}-${String(now.getDate()).padStart(2,'0')} ${String(now.getHours()).padStart(2,'0')}:${String(now.getMinutes()).padStart(2,'0')}:${String(now.getSeconds()).padStart(2,'0')}`; setScanTime(timeStr); }; // 点击OK返回首页逻辑 const handleConfirm = () => { // 回传参数到首页,merge:true避免覆盖首页其他路由参数 navigation.navigate({ name: 'Home', params: { barcodeContent: scannedData, scanTime: scanTime }, merge: true }); } if (hasPermission === null) return <Text style={{padding: 50}}>请求相机权限中...</Text> if (hasPermission === false) return <Text style={{padding: 50}}>无相机权限,无法使用扫码功能</Text> return ( <View style={styles.container}> <BarCodeScanner onBarCodeScanned={handleBarCodeScanned} style={StyleSheet.absoluteFillObject} /> {scannedData && ( <View style={styles.confirmBox}> <Text>已扫到条码:{scannedData}</Text> <Text>扫码时间:{scanTime}</Text> <Button title="确认返回首页" onPress={handleConfirm} /> </View> )} </View> ) } const styles = StyleSheet.create({ container: { flex: 1 }, confirmBox: { position: 'absolute', bottom: 100, left: 20, right: 20, backgroundColor: '#fff', padding: 20, borderRadius: 8, gap: 15 } })
常见传值失败原因排查
- 不要在扫码页用
navigation.push('Home')传参,会重复创建首页实例导致栈结构混乱 - 不要只在首页的
useEffect(() => {}, [])(组件首次挂载触发)里取route.params,从子页返回时首页不会重新挂载,该钩子不会执行 - 不要直接给
goBack()传参,多数React Navigation版本不支持该写法 - 取完参数记得清空路由缓存,避免下次进入首页重复展示历史扫码结果
内容的提问来源于stack exchange,提问作者Dani
相关产品推荐
相关产品推荐

