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
.
handleScroll
into the dependency arrayA 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.
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.