as you can see in Pinterest or other websites, when you scroll for 2 or 3 pages and you decide to click on a image or product, you will be navigated to another page, then when you press the back button, you will be also navigated to the last page you were, but also to the last position or image or product you have clicked.
i have a shopping website on next.js app router. also i am implementing the infinite scroll. the problem is when i click on a product and then i press back button it will navigate me to the top of the page and also it will not show the products which were fetched, it will try to fetch all of them again. like this is my first time i am visiting the page.
this is my page.js file
import LoadMore from "@/app/components/loadMore";
import MenuFooter from "@/app/components/menuFooter";
export default async function Home() {
return (
<main>
<LoadMore />
<MenuFooter></MenuFooter>
</main>
);
}
this is my loadMore.js file which is responsible for infinitescroll
"use client";
import { useEffect, useState } from "react";
import { useInView } from "react-intersection-observer";
import Spiner from "./ui/spiner";
import { getAllProducts } from "@/actions/productAction";
import Products from "./products";
export default function LoadMore() {
const [products, setProducts] = useState([]);
const [page, setPage] = useState(1);
const [key, setKey] = useState(2)
const { ref, inView } = useInView();
const loadMoreProducts = async () => {
const nextPage = (page) + 1;
const newProducts = (await getAllProducts(nextPage)) ?? [];
setProducts((prevProducts) => [...prevProducts, ...newProducts.items]);
setPage(newProducts.pageNum);
setKey(newProducts.pageNum)
};
useEffect(() => {
if (inView) {
loadMoreProducts();
}
}, [inView]);
return (
<>
<Products items={products} page={key}/>
<div
className="flex justify-center items-center p-4 col-span-1 sm:col-span-2 md:col-span-3"
ref={ref}
>
<Spiner />
</div>
</>
);
}
this is my products.js which is only showing the products
'use client'
import Link from "next/link"
import Image from "next/image"
import { useRouter } from "next/navigation"
import { setRecently } from "@/actions/productAction"
import { convertDigitIn } from "@/helpers/formatter"
import Masonry from 'react-masonry-css';
export default function Products({items, page}){
const router = useRouter()
const breakpointColumnsObj = {
default: 4, // For large screens
1100: 3, // Medium screens
768: 2, // Tablets
500: 2, // Mobile
};
return(
<Masonry
breakpointCols={breakpointColumnsObj}
className="flex w-auto"
columnClassName="grid-column"
>
{items.map(item => (
<div key={item.id} className="p-1">
<Link
href={`/shop/product/${item.barCode}/${item.nam_model}`}
>
<Image
src={``}
className="w-full h-auto object-cover rounded-2xl"
width={0}
height={0}
sizes="100vw"
onError={(e) => {
e.target.id = "/images/10043.webp";
e.target.srcset = "/images/10043.webp";
}}
/>
</Link>
</div>
))}
</Masonry>
)
}
i have tried to get the first and second page (each page is 12 products) and pass it to products without loadmore component, in the page.js file
and the result was really nice, i could turn back to my last clicked or last posotion, but with the loadmore (and i actually need the infinite scroll) i cant achieve that, i think the problem is with the logic of infinite scroll
When user clicks on any product and navigate you can store the currentPage value from the "page" state and id of that product in localStorage or context where ever it suits you. Then when user click back and land on this page back you can pass stored currentPage value to the fetcher and fetch all products until that page this will initially render that clicked product then when products are render you can use scrollTo and provide that product id then it will scroll to that product user clicked when navigating.
NOTE: To initially get back user to that product(clicked product) you should have that product in DOM.