Search code examples
next.jsnext.js13

How to make the Server component whenever the URL parameters changes


Can someone enlighten me on this? is it possible to trigger a re-fetch of data whenever the url parameter changes? because I tried this and it won't work, on context I'm using router.navigate instead of link and also doesn't work. Below is the code for your reference.

// Page.tsx

const Page = async (searchParams: { [key: string]: string | string[] | undefined }) => {
  const page = typeof searchParams.page === 'string' ? Number(searchParams.page) : 1
  const collections = await getCollections({ page })

  return (
    <>
      <div className={styles.categoryWrapper}>
        {collections?.data?.map(collection => <Category data={collection} key={collection?.id} />)}
      </div>
      <Pagination type="collection" />
    </>
  )
}

export default Page

// Pagination.tsx

const Pagination: FC<{ type: 'collection' | 'products' }> = ({ type }) => {
  const router = useRouter()
  const pathname = usePathname()
  const searchParams = useSearchParams()
  const { collection_length, product_length, default_pageSize } = useAppSelector(state => state.appData.website)
  const initialPage = parseInt(searchParams.get('page') || '1', 10)
  const length = Math.ceil(type === 'collection' ? collection_length / default_pageSize : product_length / default_pageSize)
  const [currentPage, setCurrentPage] = useState(initialPage)

  const handleNextPage = () => {
    if (currentPage < length) {
      setCurrentPage(currentPage + 1)
    }
  }

  const handlePreviousPage = () => {
    if (currentPage > 1) {
      setCurrentPage(currentPage - 1)
    }
  }

  useEffect(() => {
    const current = new URLSearchParams(Array.from(searchParams.entries()))

    if (currentPage === 1) {
      current.delete('page')
    } else {
      current.set('page', currentPage.toString())
    }

    const search = current.toString()
    const query = search ? `?${search}` : ''
    router.push(`${pathname}${query}`)
    router.refresh()
  }, [currentPage, router, pathname, searchParams])

  return (
    <div className={classNames(styles.pagination, roboto.className)}>
      <span onClick={handlePreviousPage}>
        <FaArrowLeft />
      </span>
      {Array.from(Array(length), (_, x) => (
        <span key={x} onClick={() => setCurrentPage(x + 1)}>
          {x + 1}
        </span>
      ))}
      <span onClick={handleNextPage}>
        next
      </span>
    </div>
  )
}
  • I tried using the link component.
  • forced adding of url page parameter using router.refresh

Solution

  • You are using searchParams as an argument of the function, while it should be inside an object. You are not using searchParams correctly in your page component:

    interface PageProps {
       searchParams?: {
          page?: string 
       }
    }
    const Page = async ({ searchParams }: PageProps) => {
       const page = searchParams && typeof searchParams.page === "string" ? Number(searchParams.page) : 1;
       ...
    }
    

    This way whenever you call router.push(...), the page will have new searchParams