如何一次扫描一个条码? [反应本机相机]

How to scan one barcode per time? [react-native-camera]

实际上我是 React 的新手,我正在尝试制作一个简单的条形码扫描仪,它在警报中显示扫描的条形码,在警报中按 "OK" 后,用户应该能够扫描另一个条形码。

问题是条形码被连续扫描,当警报出现时,它每秒隐藏和显示警报。

我试图做这样的事情来只显示一次警报,如果按下确定可以再次显示警报,但只有在按下确定但没有效果的情况下..

  onBarCodeRead = (e) => {
    if(!this.alertPresent){
      this.alertPresent = true;
          Alert.alert(
            "Barcode type is " + e.type,
            "Barcode value is " + e.data,
            [
                 {text: 'OK', onPress: () => this.alertPresent = false;},
            ],
              {cancelable: false},
          );
      }
  }

这里是Barcode.JS

的完整代码
import React, { Component } from 'react';
import { Button, Text, View,Alert } from 'react-native';
import { RNCamera } from 'react-native-camera';
import BarcodeMask from 'react-native-barcode-mask';
class ProductScanRNCamera extends Component {

  constructor(props) {
    super(props);
    this.camera = null;
    this.barcodeCodes = [];
    this.alertPresent = false;
    this.state = {
      camera: {
        flashMode: RNCamera.Constants.FlashMode.auto,
      }
    };
  }

  onBarCodeRead = (e) => {
    if(!this.alertPresent){
      this.alertPresent = true;
          Alert.alert(
            "Barcode type is " + e.type,
            "Barcode value is " + e.data,
            [
                 {text: 'OK', onPress: () => this.alertPresent = false;},
            ],
              {cancelable: false},
          );
      }
  }


  pendingView() {
    return (
      <View
      style={{
        flex: 1,
        backgroundColor: 'lightgreen',
        justifyContent: 'center',
        alignItems: 'center',
      }}
      >
      <Text>Waiting</Text>
      </View>
    );
  }

  render() {


    return (
      <View style={styles.container}>
      <RNCamera
      ref={ref => {
        this.camera = ref;
      }}
      defaultTouchToFocus
      flashMode={this.state.camera.flashMode}
      mirrorImage={false}
      onBarCodeRead={this.onBarCodeRead.bind(this)}
      onFocusChanged={() => {}}
      onZoomChanged={() => {}}
      style={styles.preview}
      >
      <BarcodeMask/>
      </RNCamera>
      </View>
    );
  }
}

使用 setState 来设置 component.setState 的状态将获取对象并更新组件的状态

检查下面的代码

import React, { Component } from 'react';
import { Button, Text, View, Alert } from 'react-native';
import { RNCamera } from 'react-native-camera';
import BarcodeMask from 'react-native-barcode-mask';
class ProductScanRNCamera extends Component {

  constructor(props) {
    super(props);
    this.camera = null;
    this.barcodeCodes = [];
    this.showAlert = true;
    this.state = {
      camera: {
        flashMode: RNCamera.Constants.FlashMode.auto,
      }
    };
  }

  onBarCodeRead = (e) => {
    if (this.state.alertPresent) {
      this.setState({ showAlert: false });
      Alert.alert(
        "Barcode type is " + e.type,
        "Barcode value is " + e.data,
        [
          { text: 'OK', onPress: () =>console.log('ok')  },
        ],
        { cancelable: false },
      );
    }
  }


  pendingView() {
    return (
      <View
        style={{
          flex: 1,
          backgroundColor: 'lightgreen',
          justifyContent: 'center',
          alignItems: 'center',
        }}
      >
        <Text>Waiting</Text>
      </View>
    );
  }

  render() {

    return (
      <View style={styles.container}>
        <RNCamera
          ref={ref => {
            this.camera = ref;
          }}
          defaultTouchToFocus
          flashMode={this.state.camera.flashMode}
          mirrorImage={false}
          onBarCodeRead={this.onBarCodeRead.bind(this)}
          onFocusChanged={() => { }}
          onZoomChanged={() => { }}
          style={styles.preview}
        >
          <BarcodeMask />
        </RNCamera>
      </View>
    );
  }
}

这里的技巧是用内部状态修改 barcodeTypes 道具。

const defaultBarcodeTypes = [// should be all Types from RNCamera.Constants.BarCodeType];

class ProductScanRNCamera extends Component {
   state = {
      // your other states
      barcodeType: '',
      barcodeValue: '',
      isBarcodeRead: false // default to false
   }

   onBarcodeRead(event) {
      this.setState({isBarcodeRead: true, barcodeType: event.type, barcodeValue: event.data});
   }

   // run CDU life-cycle hook and check isBarcodeRead state
   // Alert is a side-effect and should be handled as such.
   componentDidUpdate() {
      const {isBarcodeRead, barcodeType, barcodeValue} = this.state;
      if (isBarcodeRead) {
         Alert.alert(barcodeType, barcodeValue, [
           { 
               text: 'OK', 
               onPress: () => {
                   // Reset everything 
                   this.setState({isBarcodeRead: false, barcodeType: '', barcodeValue: ''})
               }
           }
         ]);
      }

   }

   render() {
      const {isBarcodeRead} = this.state;
      return (
         <RNCamera {...your other props} barcodeTypes={isBarcodeRead ? [] : defaultBarcodeTypes}>
            <BarcodeMask />
         </RNCamera>
      )

   }
}

钩子版本更干净

const ProductScanRNCamera = () => {
   const [isBarcodeRead, setIsBarcodeRead] = useState(false);
   const [barcodeType, setBarcodeType] = useState('');
   const [barcodeValue, setBarcodeValue] = useState('');

   useEffect(() => {
      if (isBarcodeRead) {
          Alert.alert(
             barcodeType, 
             barcodeValue, 
             [
                {
                    text: 'OK',
                    onPress: () => {
                        // reset everything
                        setIsBarcodeRead(false);
                        setBarcodeType('');
                        setBarcodeValue('');
                    }
                }
             ]
          );
      }

   }, [isBarcodeRead, barcodeType, barcodeValue]);

   const onBarcodeRead = event => {
      if (!isBarcodeRead) {
         setIsBarcodeRead(true);
         setBarcodeType(event.type);
         setBarcodeValue(event.data);
      }
   }

   return (
      <RNCamera {...your props} 
                onBarCodeRead={onBarcodeRead} 
                barcodeTypes={isBarcodeRead ? [] : defaultBarcodeTypes}>
         <BarcodeMask />
      </RNCamera>
   )
}