Search code examples
javascriptreactjsreact-hooksreact-redux

gain access of the variable that stores the useSelector in my handler function


I am trying to access the students variable by putting its value in a state then accessing that state in my handler function but it always returns an empty array.

const students = useSelector((state) => state.students);
useEffect(() => {
  setdata(students);
  console.log(data);
}, [])
const handleScanWebCam = (result, error) => {
  if (result) {
    console.log(data)

    const list = data.filter(function (student) {
      return student.id === result.text;
    })
            
    setScanResultWebCam({
      id: list.id,
      grade: list.grade,
      name: list.name,
      section: list.section
    });

  }
}

this is my full code

function QrScanner() {
  const dispatch = useDispatch(getStudents())

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

  const students = useSelector((state) => state.students);

  const [scanResultWebCam, setScanResultWebCam ] = useState({
    id: '',
    grade: '',
    name: '',
    section:''
  });

  const [openVerifier, setOpenVerifier] = useState(false);
  const [data, setdata] = useState([]);

  useEffect(() => {
    setdata(students);
    console.log(data);
  }, [])

  const handleScanWebCam = (result, error) => {
    if (result) {
      const list = data.filter(function (student) {
        return student.id === result.text;
      })
            
      setScanResultWebCam({
        id: list.id,
        grade: list.grade,
        name: list.name,
        section: list.section
      });

      setOpenVerifier(true);
    }
  }

  return (
    <>
      <NavBar />
      <Container
        sx={{
          display: 'flex',
          marginTop: '4rem',
          flexWrap: 'wrap',
          gap: '12px',
          width: '90%'
        }}
      >
        <Box
          sx={{
            width: '50%',
            border: 'solid',
            display: 'flex',
            flex: '1'
          }}
        >
          <QrReader
            scanDelay={500}
            containerStyle={{ width: '25rem', margin: 'auto'}}
            onResult={handleScanWebCam}
            // onError={handleErrorWebcam}
          />
        </Box>
        <PopupVerifier 
          details={scanResultWebCam}
          verifier={openVerifier}
          handleClose={() => handleClose()}
        />
      </Container>
    </>
  )
}

Solution

  • If you need to cache a "duplicate" of the selected students state then I'd recommend caching students in a React ref that can have its current value read at any time during the component lifecycle, especially in stale closures.

    Example:

    function QrScanner() {
      const dispatch = useDispatch(getStudents());
    
      useEffect(() => {
        dispatch(getStudents());
      }, [dispatch]);
    
      const students = useSelector((state) => state.students);
      const studentsRef = React.useRef(students);
    
      useEffect(() => {
        studentsRef.current = students;
      }, [students]);
    
      ...
    
      const handleScanWebCam = (result, error) => {
        if (result) {
          const list = studentsRef.current.find(
            (student) => student.id === result.text
          );
    
          if (list) {
            setScanResultWebCam(list);
          }
    
          setOpenVerifier(true);
        }
      };
    
      return (
        ...
      );
    }