'React: I can't get updated state values in the onScroll function

Task: I am trying to implement dynamic loading of content when scrolling for a reaction. I have an onScroll function to listen for a scroll event, which switches the isFetching variable to true when the page is scrolled all the way down. When isFetching === true, the code from useEffect is executed and the content is loaded. Everything works as it should, but I need to add another condition to onScroll, which is triggered while the amount of loaded data is < the total amount of data.

Problem: I have variables schoolResults and schoolResultsCount, which contain the number of loaded data and the total amount of data, but they are not updated when scrolling, they are always 0 when scrolling. I understand that I can transfer the function to useEffect or use a condition in useEffect and everything will work as I need. But I don't understand why the updated values of external variables are not available in the function?

Thank you for your help!

export default function Results(props: Props) {
   const location = useLocation();

   const [isLoading, setLoading] = useState<boolean>(false);
   const [isFetching, setFetching] = useState<boolean>(false);
   const [schoolResults, setSchoolResults] = useState<SchoolEvent[]>([]);
   const [schoolResultsCount, setSchoolResultsCount] = useState<number>(0);
   const [currentPage, setCurrentPage] = useState<number>(1);

   const { school } = props;
   const { id: schoolId } = school;


   useEffect(() => {
      setLoading(true);

      const promises = [
         getSchoolEvents(schoolId, getFilterForAllSchoolResults()),
         getSchoolEventsCount(schoolId, getFilterForAllSchoolResults())
      ];

      Promise.all(promises).then(([events, eventsCountObj]) => {
         setSchoolResults(events);
         setSchoolResultsCount(eventsCountObj.count);
         setLoading(false);
      });
   }, [location.search]);

   useEffect(() => {
      if (isFetching) {

         const queryFilter = {
            ...getFilterForAllSchoolResults(),
            skip: currentPage * LIMIT
         };

         getSchoolEvents(schoolId, queryFilter)
            .then((events) => {
               setSchoolResults([...schoolResults, ...events]);
               setCurrentPage(prevState => prevState + 1);
            })
            .finally(() => setFetching(false));
      }
   }, [isFetching]);

   useEffect(() => {
      document.addEventListener('scroll', onScroll);

      return function () {
         document.removeEventListener('scroll', onScroll);
      }
   }, []);

   const onScroll = (event: Event) => {
      const { target } = event;

      const scrollHeight = propz.get(target, ['documentElement', 'scrollHeight']);
      const scrollTop = propz.get(target, ['documentElement', 'scrollTop']);
      const windowInnerHeight = window.innerHeight;

      const isBottomOfPage = scrollHeight - (scrollTop + windowInnerHeight) < 100;

      // console.log('schoolResults', schoolResults.length); //The value is 0. Not updated. Why?
      // console.log('schoolResultsCount', schoolResultsCount); // The value is 0. Not updated. Why?

      if (isBottomOfPage /*&& schoolResults.length > schoolResultsCount*/) {
         setFetching(true);
      };
   };

   if (isLoading) {
      return <Loader />;
   }

   return (//Some JSX)
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source