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

TypeError: Cannot read properties of null (reading 'x') at Object.checkImageConstraints #486

Open
lusivelin opened this issue Feb 15, 2023 · 15 comments
Labels

Comments

@lusivelin
Copy link

Hello guys, I try to install quagga2 with typescript.
I've got this issue.

Quagga.init(config, (err) => console.log(err))

The err obj return as following error.

message: "Cannot read properties of null (reading 'x')"
stack: "TypeError: Cannot read properties of null (reading 'x')
at Object.checkImageConstraints (http://localhost:5173/node_modules/.vite/deps/@ericblade_quagga2.js?v=92f8696d:1304:97)
at http://localhost:5173/node_modules/.vite/deps/@ericblade_quagga2.js?v=92f8696d:5068:42
at Object.trigger (http://localhost:5173/node_modules/.vite/deps/@ericblade_quagga2.js?v=92f8696d:4854:24)
at http://localhost:5173/node_modules/.vite/deps/@ericblade_quagga2.js?v=92f8696d:5125:27"

Here is my tsconfig.json
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"allowJs": false,
"skipLibCheck": true,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "Node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
}

@github-actions
Copy link

Thank you for filing an issue! Please be patient. :-)

@ericblade
Copy link
Owner

What does your config object look like? Thanks!

@lusivelin
Copy link
Author

@ericblade Thanks for your time, here is my config obj.

{
      inputStream: {
        type: "LiveStream",
        constraints: {
          width: 640,
          height: 480,
          facingMode: "environment",
        },
      },
      locator: {
        patchSize: "large",
        halfSample: true,
        debug: {
          showCanvas: true,
          showPatches: false,
          showFoundPatches: false,
          showSkeleton: false,
          showLabels: false,
          showPatchLabels: false,
          showRemainingPatchLabels: false,
          boxFromPatches: {
            showTransformed: true,
            showTransformedBox: true,
            showBB: true,
          },
        },
      },
      numOfWorkers: 4,
      frequency: 10,
      decoder: {
        readers: ["code_128_reader", "ean_reader"],
        debug: {
          drawBoundingBox: true,
          showFrequency: true,
          drawScanline: true,
          showPattern: true,
        },
      },
      locate: true,
}

@ericblade
Copy link
Owner

Hmm. Looks like something that "Vite" is doing to mangle the node_modules in some way that it shouldn't be. Similar to when you have a bad webpack config and it runs all it's parsing/compression steps on node_modules that it shouldn't do.

None of the lines given in the error message make any sense at all given the original source code. Something in your packaging/bundling/serving setup is making a mess out of things.

@SidMorad
Copy link

SidMorad commented Jun 10, 2023

I did manage to get this library working with "Vite", and following info might help:

I can reproduce exact same error with following change:

-import BarcodeScanner from '../../components/Scanner'
+const BarcodeScanner = lazy(() => import('../../components/Scanner'))

So, I can't lazy load src/components/Scanner.js at the moment, if you find a solution for it, please let us know, thanks.

...
  numOfWorkers: 0,
  locate: false,
}

I was not able to receive any result with locate : true

These were my tested versions:

  "vite": "^4.3.8",
  "react": "^18.2.0",

One more thing I notice, useLayerEffect works as expected in development but for production build I had to use useEffect. can this have side-effects(?).

Please let me know if sharing something else could help?
And thank you for giving us an open source alternative.
Cheers

p.s. my vite.config.ts doesn't include any special plugin related to this library, but for some other issue, I had to change it like below, and my code doesn't compile without it, so I'm not sure if that is necessary for this library too or not

import react from '@vitejs/plugin-react'
import { defineConfig } from 'vite'

export default defineConfig({
  plugins: [
    react({
      babel: {
        parserOpts: {
          plugins: ['decorators-legacy'],
        },
      },
    }),
...

@ericblade
Copy link
Owner

that all seems very strange. especially the decorators part, since I know for sure there are no decorators used in Quagga or Quagga2

If you could put up a repo I could clone with a minimal demonstration of the issues, I could give it a few pokes and see what I can come up with :)

@SidMorad
Copy link

SidMorad commented Jul 9, 2023

At the moment, event lazy loading does work for me, so I don't have any issue with my setup, although I do see the original error log in my console time-to-time, but it doesn't break the scanning process for me. Perhaps this bug is helping me to recover, IDK.

I think upgrading React example to version 18 would be nice, and this error log might come up during the upgrade.

I would be happy to create a pull request for React example or create an independent repo for showing my working example, please let me know which one is preferred. thanks

@ericblade
Copy link
Owner

I just did a quick and dirty changeover of it to use create-react-app .. and react 18...

i think at this point, everyone is using that, so it's probably better this way.

@ericblade
Copy link
Owner

Hey there .. i've started seeing this error in the updated quagga2-react-example.

Not sure specifically why it's being caused, but disabling React StrictMode fixes it.

@SidMorad @lusivelin

I still don't really know anything about Vite, but if you're using React in StrictMode then you may be seeing the problem for the exact same reason I am -- along with the other problem that crops in with StrictMode on, while running in development -- the camera sticks "on" even though Quagga is no longer using it. That's an undesireable state, for sure!

I'm doing a little poking with the scanner component in the sample app to see if I can mitigate that, but you may want to turn StrictMode off if you are using that, and your project isn't built for production.

@ericblade
Copy link
Owner

So.. what's happening in StrictMode, is that it's calling the effect that starts it, immediately unmounting it, and remounting it, to call it again. Browser doesn't have time to even get it started, before it's calling stop(), so stop fails, because nothing has started yet, but then the start goes through, and so then it tries to start it again on the second mounting.

SO! what I've done with my sample, is added a one tick delay before starting, and when stop is triggered it toggles a boolean that flags the start to not fire if that is true.

so, might have a look at the useLayoutEffect() call in https://github.com/ericblade/quagga2-react-example/blob/abf7a65d5a4bb2e97f4b8dbb00b94dc4cf14f53a/src/Scanner.js#L92

There might be a better? way to fix this? but I think this is probably fine.

Please let me know how that goes. Thanks! :)

@SidMorad
Copy link

@ericblade I do confirm your fix does work for my setup too. So there is no error log in the console and camera gets turn off as expected. I'm glad we cloud close this issue. Thanks! :)

@ericblade
Copy link
Owner

I think when I have time to look at this a little more indepth, I'll see what happens if you just call Quagga.init() back to back and see if that can be handled internally any better, but for right now, I think a 1 tick delay isn't going to harm anyone

@ericblade ericblade added the bug label Jul 18, 2023
@ericblade
Copy link
Owner

I'm actually leaning towards this being the correct solution, as Quagga.init() is basically an asynchronous call, but doesn't provide any way to abort it if the user (or the StrictMode) tries to stop it before it can complete. So, it's effectively the same thing as a remote network call that you need to ignore the results from if the user cancels the operation.

I do think there might still be a way to clean this up some library side, will investigate. Though might be something that goes in the next major release.

@ericblade
Copy link
Owner

... thought before i head to sleep and revisit th is ... the thing to do might be if you call Quagga.stop() while init() is happening, have it actually throw an error indicating that it was aborted, so you know not to call start().

@lusivelin
Copy link
Author

Sry I haven't look back this for long time. I just used Quagga as brute force to make it work.

https://github.com/lusivelin/barcode-scanner/blob/main/src/hooks/services/useBarCodeScanner.ts

please take a look so you can address the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants