Home > Blockchain >  App crashes on API call in frameProcessor React Native
App crashes on API call in frameProcessor React Native

Time:12-30

I am using a dependency called vision-camera-code-scanner for QR code scanning in my React Native app. I am getting QR code scan data properly. But i need to pass that data to make an API call. But when i try to do that, it crashes the application. Not sure what should i do here.

Here's my component:

import React, { useState, useCallback, useEffect, useMemo } from "react";
import { StyleSheet, Text } from "react-native";
import {
  Camera,
  useCameraDevices,
  useFrameProcessor,
} from "react-native-vision-camera";
import { useDispatch, useSelector } from "react-redux";
import * as appActions from "../../../redux/app/app.actions";
import { BarcodeFormat, scanBarcodes } from "vision-camera-code-scanner";

interface ScanScreenProps {}

const Scan: React.FC<ScanScreenProps> = () => {
  const [hasPermission, setHasPermission] = useState(false);
  const devices = useCameraDevices();
  const device = devices.back;
  const dispatch = useDispatch();
  const validateQRStatus = useSelector(validationQRSelector);

  const frameProcessor = useFrameProcessor((frame) => {
    "worklet";
    const detectedBarcodes = scanBarcodes(frame, [BarcodeFormat.QR_CODE], {
      checkInverted: true,
    });
    if (detectedBarcodes?.length !== 0) {
        const resultObj = JSON.parse(detectedBarcodes[0].rawValue);
        const paramData = `token:${Object.values(resultObj)[0]}`;
        validate(paramData);
  }, []);

  const validate = useCallback((param: string) => dispatch(appActions.validateQR(param)));

  useEffect(() => {
    (async () => {
      const status = await Camera.requestCameraPermission();
      setHasPermission(status === "authorized");
    })();
  }, []);

  return (
    device != null &&
    hasPermission && (
      <>
        <Camera
          style={StyleSheet.absoluteFill}
          device={device}
          isActive={true}
          frameProcessor={frameProcessor}
          frameProcessorFps={5}
        />
        {/* {barcodes.map((barcode, idx) => (
          <Text key={idx} style={styles.barcodeTextURL}>
            {barcode.barcodeFormat   ": "   barcode.barcodeText}
          </Text>
        ))} */}
        <Text style={styles.barcodeTextURL}>camera</Text>
      </>
    )
  );
};

export default Scan;

const styles = StyleSheet.create({
  barcodeTextURL: {
    fontSize: 20,
    color: "white",
    fontWeight: "bold",
    alignSelf: "center",
  },
});

CodePudding user response:

Your problem is that a worklet is run in a separate JS thread. If you need to call any function from your main thread you need to use runOnJS (https://docs.swmansion.com/react-native-reanimated/docs/next/api/miscellaneous/runOnJS/)


import { runOnJS } from 'react-native-reanimated';

  const frameProcessor = useFrameProcessor((frame) => {
    "worklet";
    const detectedBarcodes = scanBarcodes(frame, [BarcodeFormat.QR_CODE], {
      checkInverted: true,
    });
    if (detectedBarcodes?.length !== 0) {
        const resultObj = JSON.parse(detectedBarcodes[0].rawValue);
        const paramData = `token:${Object.values(resultObj)[0]}`;
        runOnJS(validate)(paramData);
  }, []);
  • Related