aclec / expo-zebra-scanner

11 stars 4 forks source link

State variables are not accessible #19

Open demacomsistemas opened 1 day ago

demacomsistemas commented 1 day ago

Hi everybody. I'm experiencing some strange behavior that I can't explain.

I have a state variable (an object actually) that it setted when pressing a button that also "opens" a Modal element. In this Modal I've a textinput and another button.

The state variable seems to be empty when handleZebraScanned is fired. The same code as handleZebraScanned but in the second button displays successfully the state variable in a console.log. Why is that? What I'm doing wrong? There is some React or React Native concept that I'm missing?

import * as ExpoZebraScanner from "expo-zebra-scanner"; useEffect(() => { const event = ExpoZebraScanner.addListener(e => { const {scanData, scanLabelType} = e; handleZebraScanned(scanData); });

ExpoZebraScanner.startScan();

return () => {
  try {
    ExpoZebraScanner.stopScan();
    event.remove(); //ExpoZebraScanner.removeListener(event);
  }
  catch(err) {
    console.error('Error en PedidoDetalle.jsx useEffect return():');
    console.error(err);
  }
  finally {
  }
}

},[]);

function handleZebraScanned (data) { // Here the state variable is empty } const handleNuevaCaja = () => { // ==> this function is used in the second button: onPress={() => handleNuevaCaja()} // Here the state variable is OK }

Thanks in advance Damian.

Shadic78 commented 23 hours ago

Hi Damian.

You're talking about an "state variable" but I don't get if you mean a state created with useState() that you omitted in the provided code or if you mean that the value of "scanData" is empty when handleZebraScanned() is called. Also I don't get what handleNuevaCaja() is doing right that handleZebraScanned() don't.

If your problem is what I think It is and It isn't about the package but about React Native then you are setting a state inside the addListener method of ExpoZebraScanner and you try to print it in handleZebraScanned() and you get something unexpected but in handleNuevaCaja() you get the expected value it's because the state has not been updated yet when handleZebraScanned() is called but when your modal is open the state is already updated and handleNuevaCaja() works fine. In that case you may send the state to handleZebraScanned() along scanData.

Please describe more your problem or show a more complete code snippet to be able to help you.

demacomsistemas commented 20 hours ago

Hi Shadic78, thanks for your attention.

With "state variable" I mean a state created with useState(). The value of "scanData" is ok.

My intention is that handleNuevaCaja() and handleZebraScanned() do the same, but handleNuevaCaja() is fired from button when the app is running on a cell phone or tablet other than Zebra.

I get your point, I'll try to send the state as a second parameter to handleZebraScanned() and let you know.

Also, I can upload the entire jsx file if you want to see it.

aclec commented 11 hours ago

Hi @demacomsistemas, yes, please upload the JSX file.

Also, there is something strange: you can’t use [] as dependencies in useEffect with code like that.

demacomsistemas commented 10 hours ago

Hi @aclec, @Shadic78 Again, thank you both for your attention.

Renamed as txt because is not allowed to upload jsx files. PedidoDetalle.txt

@aclec , in reference to the dependencies in my useEffect, I followed instructions of this article https://www.reactnative.express/react/hooks/useeffect for the "no dependency" or "one time" situation

demacomsistemas commented 10 hours ago

Another strange behavior: 1) I have the TC21 connected by usb-c to the Mac 2) Then run in the terminal: npx expo run:android --no-build-cache 3) The app is running on the TC21. When showing the state variable (created with useState) with the console.log in handleZebraScanned function, it is empty 4) I made some change in the jsx file (no mather what, may be just add a space character and save) and, when test again the app, the state variable has the expected value in handleZebraScanned function.

@Shadic78 , I'm not setting the state variable inside the AddListener method. It is setted in a previous operation (a button tap)

Regards Damian

Shadic78 commented 6 hours ago

@demacomsistemas Alright, so the problem isn't about this package but about React Native concepts.

I'll asume your troublesome state is "pedidoLinea". I believe whats hapenning is something called "stale state", you can read about it [here](https://dmitripavlutin.com/react-hooks-stale-closures/#:~:text=3.%20State%20closure%20in%20useEffect()).

There are two options:

  1. You can wrap your function handleZebraScanned() with a useCallback with "pedidoLinea" as a dependency an then add the funcion handleZebraScanned to the dependencies of the useEffect.
// Refactor your function to an arrow function and wrap it in useCallback.
const handleZebraScanned = useCallback((data) => { /* your code */ }, [pedidoLinea]); // Add the STATE to the dependencies

useEffect(() => {
// Your code
}, [handleZebraScanned]); // Add the FUNCTION to the dependency array
  1. If handleZebraScanned() isn't called in other parts of your code you could move it to be inside the useEffect and add the state to the dependencies.
useEffect(() => {
  function handleZebraScanned(scanData) { /* Your code */ }
  // Other code
}, [pedidoLinea); // Add the STATE to the dependencies

Side note: I see that you're working with other state variables in handleZebraScanner so whatever option you choose, the same problem will keep happening with other state variables and you can fix it by adding them all to the corresponding dependency array ex: [pedidoLinea, workingPedidoCab, listOfCajas]. Feel free to ask more questions.

That would be my answer to the problem, @aclec what do you think?

demacomsistemas commented 3 hours ago

Hi @Shadic78

Yes, you right about this: I'll asume your troublesome state is "pedidoLinea"

handleZebraScanned() isn't called in other parts of the code, so I can try both options.

I'll read about "stale state" and try your options. And let you know how it tourned out