首页 > 解决方案 > Usestate 递增 1 在 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);
        }, []);

出于某种原因,当我运行 setCurrentPage 时,这永远不会超过两个,但是如果我像这样增加它

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

它按预期工作。我猜它与 useEffect 或 setInterval 有关,但不是 100% 确定原因。

标签: javascriptreactjsuse-statereact-state-management

解决方案


代码中的每个渲染都会创建一个新handleScroll函数。

函数只传给setInterval第一次,所以currentPage这个函数里面会一直留着1,然后1 + 1就一直是2

(A) 放入handleScroll依赖数组

一个解决方案是在有新的setInterval时候创建一个新的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

显然,在这种情况下 asetTimeout可能是更好的选择,因为它总是只运行一次。

(B) 将函数传递给 setState

或者,您可以将函数传递给 setState

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

通常完全没问题,但请注意不要对效果的依赖项撒谎


推荐阅读