I made a mini library out of this, have a look att github.com/KATT/next-router-query
Last active
August 5, 2022 20:48
-
-
Save KATT/524a866021869affddf4be5754f2f672 to your computer and use it in GitHub Desktop.
`useRouterQuery()` hook to get query params on first render
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useRouter } from 'next/router'; | |
import { useMemo } from 'react'; | |
/** | |
* Ugly hack for using search params as `useRouter()` won't return it on first render | |
* @link https://gist.github.com/KATT/524a866021869affddf4be5754f2f672 | |
*/ | |
export function useRouterQuery() { | |
const router = useRouter(); | |
const { asPath, query, pathname } = router; | |
const value = useMemo(() => { | |
// if we have query params from the router, let's return that | |
if (Object.keys(query).length > 0) { | |
return query; | |
} | |
// split path by `/` or `?` | |
const pathnameParts = pathname.split(/\/|\?/); | |
const loc = | |
typeof location !== 'undefined' | |
? { | |
query: Object.fromEntries(new URLSearchParams(location.search)), | |
pathname: location.pathname, | |
} | |
: { | |
query, | |
pathname: asPath, | |
}; | |
const asPathParts = loc.pathname.split(/\/|\?/); | |
// actual query object that we wanna use | |
const actualQuery: typeof query = {}; | |
for (let index = 0; index < pathnameParts.length; index++) { | |
const part = pathnameParts[index]; | |
if (!part.startsWith('[') || !part.endsWith(']')) { | |
continue; | |
} | |
// extract real query param from `post/[id]` style routes | |
// removes first and last character | |
const key = part.slice(1, -1); | |
if (key.startsWith('...')) { | |
// catch-all route | |
const catchAllKey = key.slice(3); | |
actualQuery[catchAllKey] = asPathParts.splice(index); | |
break; | |
} | |
// append to "actual query" | |
actualQuery[key] = asPathParts[index]; | |
} | |
for (const key in loc.query) { | |
actualQuery[key] = loc.query[key]; | |
} | |
return actualQuery; | |
}, [asPath, query, pathname]); | |
return value; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Next.js apge | |
import { useRouterQuery } from '../lib/useRouterQuery'; | |
export default function MyPage(props: inferSSRProps<typeof getStaticProps>) { | |
const searchParams = useRouterQuery(); | |
const username = (props.username || searchParams.username) as string; | |
// now `username` is always a string on first render | |
} | |
export const getStaticPaths: GetStaticPaths = async () => { | |
return { | |
paths: [], | |
fallback: true, | |
}; | |
}; | |
export async function getStaticProps(context: GetStaticPropsContext<{ username: string }>) { | |
const username = context.params!.username; | |
return { | |
props: { | |
username, | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment