React本地变量endOfDocument无法更新问题求助
Hey, let's break down why your endOfDocument variable gets stuck as true once set, and fix it step by step:
The Root Causes
endOfDocumentis a plain JavaScript variable, not React state/ref: React doesn't track changes to regularletvariables. When you update it, the component doesn't re-render, and the scroll event listener (created in the initialuseEffectclosure) keeps referencing the original stale value.- Incorrect event listener cleanup: You're trying to remove a brand new empty function
() => {}instead of the actual scroll handler you added. This leaves the original listener attached, still using the oldendOfDocumentvalue. starthas the same issue: It's a plain variable, so its changes aren't tracked, and closures will hold stale versions of it.
Fix Steps
We'll refactor to use useRef for tracking endOfDocument and start (since we don't need these values to trigger UI re-renders) and fix the event handling:
1. Replace plain variables with useRef
import { useEffect, useRef, useState } from 'react'; // Inside your component: const endOfDocumentRef = useRef(false); const startRef = useRef(null); const [exerciseList, setExerciseList] = useState([]);
2. Fix the scroll event listener in useEffect
Define the handler function explicitly so we can reference it for cleanup:
useEffect(() => { const { current } = selectScroll; const handleScroll = () => { // Access the ref's current value if (!endOfDocumentRef.current && current.scrollTop + current.clientHeight >= current.scrollHeight) { getMoreExercises(); } }; current.addEventListener('scroll', handleScroll); // Cleanup with the exact same handler return () => { current.removeEventListener('scroll', handleScroll); }; }, []); // Add selectScroll to dependencies if it can change
3. Update getMoreExercises to use refs
function getMoreExercises() { if (!endOfDocumentRef.current) { let ref = null; if (selectRef.current.value !== 'All') { ref = db .collection('exercises') .where('targetMuscle', '==', selectRef.current.value); } else { ref = db.collection('exercises'); } ref .orderBy('average', 'desc') .startAfter(startRef.current) .limit(5) .get() .then((snapshots) => { startRef.current = snapshots.docs[snapshots.docs.length - 1]; if (!startRef.current) { endOfDocumentRef.current = true; } snapshots.forEach((exercise) => { setExerciseList((prevArray) => [...prevArray, exercise.data()]); }); }); } }
4. Fix the handleCategory function
Reset all relevant refs and clear the exercise list to start fresh:
function handleCategory() { endOfDocumentRef.current = false; startRef.current = null; setExerciseList([]); // Clear existing list before fetching new data getExercises(); // Fetch first page of the new category }
Why This Works
useRefvalues persist across re-renders, and their.currentproperty can be updated without triggering a re-render—ideal for tracking state that doesn't need to update the UI directly.- Storing the scroll handler in a variable lets us correctly remove it during cleanup, eliminating stale listeners.
- Resetting refs and the exercise list ensures we start from scratch when switching categories, with
endOfDocumentback tofalse.
内容的提问来源于stack exchange,提问作者ozansozuoz
相关产品推荐
相关产品推荐

