You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 12:18:24