Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Illegal constructor #154

Open
regisoc opened this issue Nov 15, 2024 · 7 comments
Open

Illegal constructor #154

regisoc opened this issue Nov 15, 2024 · 7 comments

Comments

@regisoc
Copy link

regisoc commented Nov 15, 2024

Hello,

Short version: maybe I am just blind after some hours spent on that. There is an annoying "Illegal constructor" appearing and I cannot figure out why.

I am trying to set up the React VideoCapture element as mentioned here.

It looks like this:

`VideoCapture` element
import React from 'react';

import '../dynamsoft.config';

// --Change starts
// For some reason, import from Dynamsoft does not work. But the library is creating a global
// `Dynamsoft` object that has all the library contents.

// @ts-ignore
import "dynamsoft-camera-enhancer";
// @ts-ignore
import "dynamsoft-capture-vision-router";
// @ts-ignore
import "dynamsoft-utility";

const Dynamsoft = (window as any).Dynamsoft;
const CameraEnhancer = Dynamsoft.DCE.CameraEnhancer;
const CameraView = Dynamsoft.DCE.CameraView;
const CaptureVisionRouter = Dynamsoft.CVR.CaptureVisionRouter;
const MultiFrameResultCrossFilter = Dynamsoft.Utility.MultiFrameResultCrossFilter;

// -- Change end

const componentDestroyedErrorMsg = "VideoCapture Component Destroyed";

class VideoCapture extends React.Component<{ onSubmit: Function }, {}> {
  cameraViewContainer: React.RefObject<HTMLDivElement> = React.createRef();

  resolveInit?: () => void;
  pInit: Promise<void> = new Promise((r) => (this.resolveInit = r));
  isDestroyed = false;

  cvRouter?: typeof Dynamsoft.CVR;
  cameraEnhancer?: typeof Dynamsoft.CE;

  async componentDidMount() {
    try {
      // Create a `CameraEnhancer` instance for camera control and a `CameraView` instance for UI control.
      const cameraView = await CameraView.createInstance();
      if (this.isDestroyed) {
        throw Error(componentDestroyedErrorMsg);
      } // Check if component is destroyed after every async

      this.cameraEnhancer = await CameraEnhancer.createInstance(cameraView);
      if (this.isDestroyed) {
        throw Error(componentDestroyedErrorMsg);
      }

      // Get default UI and append it to DOM.
      this.cameraViewContainer.current!.append(cameraView.getUIElement());

      // Create a `CaptureVisionRouter` instance and set `CameraEnhancer` instance as its image source.
      this.cvRouter = await CaptureVisionRouter.createInstance();
      if (this.isDestroyed) {
        throw Error(componentDestroyedErrorMsg);
      }
      this.cvRouter.setInput(this.cameraEnhancer);

      // Define a callback for results.
      this.cvRouter.addResultReceiver({
        onDecodedBarcodesReceived: (result: any) => {
          if (!result.barcodeResultItems.length) return;

          for (let item of result.barcodeResultItems) {
            this.props.onSubmit(item.text);
          }
        },
      });

      // Filter out unchecked and duplicate results.
      const filter = new MultiFrameResultCrossFilter();
      // Filter out unchecked barcodes.
      filter.enableResultCrossVerification("barcode", true);
      // Filter out duplicate barcodes within 3 seconds.
      filter.enableResultDeduplication("barcode", true);
      await this.cvRouter.addResultFilter(filter);
      if (this.isDestroyed) {
        throw Error(componentDestroyedErrorMsg);
      }

      // Open camera and start scanning single barcode.
      await this.cameraEnhancer.open();
      if (this.isDestroyed) {
        throw Error(componentDestroyedErrorMsg);
      }
      await this.cvRouter.startCapturing("ReadSingleBarcode");
      if (this.isDestroyed) {
        throw Error(componentDestroyedErrorMsg);
      }
    } catch (ex: any) {
      if ((ex as Error)?.message === componentDestroyedErrorMsg) {
        console.log(componentDestroyedErrorMsg);
      } else {
        let errMsg = ex.message || ex;
        console.error(errMsg);
        console.log("ERROR HERE");
        console.log(ex);
        alert(errMsg);
      }
    }

    // Resolve pInit promise once initialization is complete.
    this.resolveInit!();
  }

  async componentWillUnmount() {
    this.isDestroyed = true;
    try {
      // Wait for the pInit to complete before disposing resources.
      await this.pInit;
      this.cvRouter?.dispose();
      this.cameraEnhancer?.dispose();
    } catch (_) {}
  }

  shouldComponentUpdate() {
    // Never update UI after mount, sdk use native way to bind event, update will remove it.
    return false;
  }

  render() {
    return (
      <div ref={this.cameraViewContainer} style={{  width: "100%", height: "70vh" }}></div>
    );
  }
}

export default VideoCapture;

The VideoCapture component is embedded is another QRCodeReader element.

`QRCodeReader` element
import { useState } from 'react';
import VideoCapture from "./VideoCapture";

const QRCodeReader = (props) => {
    const [errors, setErrors] = useState(null);

    const onSubmit = async (param) => {
        try {
            const isUpdated = await props.onSubmit(param);
            if (isUpdated) {
                setErrors(null);
            }
        } catch(error){
            setErrors(error);
        }
    }

    return (
        <div>
            <VideoCapture onSubmit={onSubmit} />
            {errors}
        </div>
    );
}

export default QRCodeReader;

Until here, everything works well. Using the QRCodeReader element, it can scan QRCode and extract the item elements. Nice.

The issue happens after that, when I try to embed the QRCodeReader element into a QRModal Element.
Elements looks like this VideoCapture <- QRCodeReader <- QRModal.

We want to use them in a process that is the following:

  • first scan: uses the QRCodeReader (full page reader).
  • updates the page to match info in the QRCode, loads a list of items from db on the page, each item has a scan modal button to trigger the QRModal, to access the detail of each item, we must scan again using the modal.
  • second scan: uses the QRModal (modal reader) -> fails consistently with the same error.
`QRModal` element
import React, {useEffect, useState} from 'react';
import PropTypes from 'prop-types';
import Modal from 'Modal';
import QRCodeReader from './QRCodeReader';

/**
 * Widget to access a profile using a QR code
 *
 * @param {object} props - React props
 *
 * @return {ReactDOM}
 */
const QRModal = (props) => {
  const [code, setCode] = useState(null);

  useEffect(() => {
  }, []);

  return (
    <Modal
      onClose={() => {
        props.onClose();
      }}
      show={true}
      title={props.modalTitle}
    >
      <QRCodeReader onSubmit={(c) => {
        if (c === code) return;
        setCode(c);
        props.onScan(c);
      }} />
    </Modal>
  );
}

QRModal.defaultProps = {
  modalTitle: 'Scan QR Code',
};

QRModal.propTypes = {
  modalTitle: PropTypes.string,
};

export default QRModal;

This is throwing a Type Error: Illegal constructor. apparently coming from CameraView.createInstance().

I also tried to directly shortcut QRModal to directly call another VideoCapture class (VideoCapture2 is a copy of VideoCapture). Same result.

image

@Keillion
Copy link
Collaborator

[email protected]

This version can solve your problem.

===
Although this problem can be solved this way, I still ask for code that can reproduce the problem.

@Keillion
Copy link
Collaborator

I guess some framework/library reasons caused our SDK to be loaded repeatedly.

@regisoc
Copy link
Author

regisoc commented Nov 18, 2024

Thanks for the answer @Keillion I will try to test it today.

@regisoc
Copy link
Author

regisoc commented Nov 20, 2024

Hello @Keillion it looks like 10.4.2002-beta-202410310215 solved the issue we had.
I see it has a beta label. Will this be merged in the next version?

@Keillion
Copy link
Collaborator

Yes, we plan to merge it in 10.6.x.

You can just use this beta version. We will support it.

@regisoc
Copy link
Author

regisoc commented Nov 21, 2024

Thanks for your help :) Closing.

@regisoc regisoc closed this as completed Nov 21, 2024
@Keillion
Copy link
Collaborator

I keep showing this bug until we fix it in a official release.

@Keillion Keillion reopened this Nov 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants