简体   繁体   中英

Usestate increment by 1 not working in setInterval

    const [currentPage, setCurrentPage] = useState(1);     
    const handleScroll = () => {
            const gridContainer = document.querySelector(".grid");
    
            const totalPages = Math.ceil(
                gridContainer.scrollWidth / gridContainer.clientWidth + -0.1
            );
            setTotalPages(totalPages);
    
            const scrollPos =
                gridContainer.clientWidth + gridContainer.scrollLeft + 2;
            if (gridContainer.scrollWidth > scrollPos) {
                gridContainer.scrollBy({
                    left: gridContainer.clientWidth + 20.5,
                    behavior: "auto",
                    block: "center",
                    inline: "center",
                });
                setCurrentPage(currentPage + 1);
            } else {
                setCurrentPage(1);
                gridContainer.scrollTo(0, 0);
            }
        };
    
        useEffect(() => {
            setInterval(() => {
                document.querySelector(".grid") && handleScroll();
            }, 5000);
        }, []);

For some reason this will never go past two when I run the setCurrentPage but if I increment it like this

 <button onClick={() => setCurrentPage(currentPage + 1)}>
                    +1
  </button

It works as expected. I am guessing it has something to do with the useEffect or the setInterval but not really a 100% sure why.

A new handleScroll function is created on every render in your code.

The function is passed to setInterval only the first time, so the currentPage inside this function will always stay 1 , then 1 + 1 is always 2 .

(A) Put handleScroll into the dependency array

A solution would be to create a new setInterval whenever there is a new handlescroll :

    useEffect(() => {
        let interval = setInterval(() => {   // <--- store the interval (to be able to remove it later)
            document.querySelector(".grid") && handleScroll();
        }, 500);

        // -- remove the interval inside the clean up function of useEffect
        return () => {
            clearInterval( interval );
        }
    }, [ handleScroll ]); // <--- add handleScroll to the dependency array

Obviously, in this case a setTimeout might be a better choice, as it always runs only once anyway.

(B) Pass a function to setState

Alternatively you can pass a function to setState :

setCurrentPage((prevCurrentPage) => prevCurrentPage + 1);

That is generally totally ok, but be careful not to lie about your effect's dependencies .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM