You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. 'use client'
  2. import { usePathname, useRouter, useSearchParams } from 'next/navigation'
  3. import { useState } from 'react'
  4. type UseTabSearchParamsOptions = {
  5. defaultTab: string
  6. routingBehavior?: 'push' | 'replace'
  7. searchParamName?: string
  8. disableSearchParams?: boolean
  9. }
  10. /**
  11. * Custom hook to manage tab state via URL search parameters in a Next.js application.
  12. * This hook allows for syncing the active tab with the browser's URL, enabling bookmarking and sharing of URLs with a specific tab activated.
  13. *
  14. * @param {UseTabSearchParamsOptions} options Configuration options for the hook:
  15. * - `defaultTab`: The tab to default to when no tab is specified in the URL.
  16. * - `routingBehavior`: Optional. Determines how changes to the active tab update the browser's history ('push' or 'replace'). Default is 'push'.
  17. * - `searchParamName`: Optional. The name of the search parameter that holds the tab state in the URL. Default is 'category'.
  18. * @returns A tuple where the first element is the active tab and the second element is a function to set the active tab.
  19. */
  20. export const useTabSearchParams = ({
  21. defaultTab,
  22. routingBehavior = 'push',
  23. searchParamName = 'category',
  24. disableSearchParams = false,
  25. }: UseTabSearchParamsOptions) => {
  26. const pathnameFromHook = usePathname()
  27. const router = useRouter()
  28. const pathName = pathnameFromHook || window?.location?.pathname
  29. const searchParams = useSearchParams()
  30. const searchParamValue = searchParams.has(searchParamName) ? decodeURIComponent(searchParams.get(searchParamName)!) : defaultTab
  31. const [activeTab, setTab] = useState<string>(
  32. !disableSearchParams
  33. ? searchParamValue
  34. : defaultTab,
  35. )
  36. const setActiveTab = (newActiveTab: string) => {
  37. setTab(newActiveTab)
  38. if (disableSearchParams)
  39. return
  40. router[`${routingBehavior}`](`${pathName}?${searchParamName}=${encodeURIComponent(newActiveTab)}`)
  41. }
  42. return [activeTab, setActiveTab] as const
  43. }