2

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>
    </>
  )
}
Drew Reese
  • 165,259
  • 14
  • 153
  • 181

2 Answers2

1

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 (
    ...
  );
}
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
1

You have using from react-redux. so you dont need to set student state.

and dispatch is used for change in store not getting data from it.

if you want to get an item from array use find instead of filter :

const list = students.find(student=>student.id===result.text);

i edit your code to :

function QrScanner() {
  
  const students = useSelector((state) => state.students);

  const [scanResultWebCam, setScanResultWebCam ] = useState({
      id: '',
      grade: '',
      name: '',
      section:''
  });
  const [openVerifier, setOpenVerifier] = useState(false);
  const handleScanWebCam = (result, error) => {
      if(result) {
          const list = students.find(student=> student.id === result.text);
          setScanResultWebCam({id: list.id, grade: list.grade, name: list.name, section: list.section});
          setOpenVerifier(true);
      }

  }

  return(
      ...
  )
}

 
Abbas Bagheri
  • 790
  • 5
  • 10