Skip to content

Instantly share code, notes, and snippets.

@iShawnWang
Last active July 27, 2019 05:52
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iShawnWang/fddaa66f0090133fd8d42cc363a7e6d4 to your computer and use it in GitHub Desktop.
Save iShawnWang/fddaa66f0090133fd8d42cc363a7e6d4 to your computer and use it in GitHub Desktop.
react-router backward hooks, support react-router 4.x | 5.x
import { __RouterContext as RouterContext, RouteComponentProps } from 'react-router'
import { useContext, useMemo, useCallback } from 'react'
import qs from 'qs'
import { Location } from 'history'
interface ParsedQuery {
[whatever: string]: any
}
export const useRouter = <T>(): RouteComponentProps<T> =>
useContext(RouterContext) as RouteComponentProps<T>
export const useLocation = (): Location => {
const { location } = useRouter()
return location
}
export const useParams = <T>(): T => {
const { location } = useRouter<T>()
// @ts-ignore
return location.query
}
export const useQuery = <T extends ParsedQuery>(): T => {
// @ts-ignore
const { query } = useLocation()
const q = useMemo(() => qs.parse(query), [query])
return q as T
}
export const useUpdateQuery = <T extends ParsedQuery>() => {
const { history } = useRouter()
const query = useQuery<T>()
const updateQuery = useCallback(
(patch: Partial<T>, merge = true): void => {
const newQuery = merge ? { ...query, ...patch } : patch
const newSearch = qs.stringify(newQuery)
history.push({ search: newSearch })
},
[history, query],
)
return updateQuery
}
export const useRouterBackward = <T>(r: RouteComponentProps<T>): RouteComponentProps<T> =>
r as RouteComponentProps<T>
export const useLocationBackward = (r: RouteComponentProps<T>): Location => {
const { location } = useRouterBackward(r)
return location
}
export const useParamsBackward = <T>(r: RouteComponentProps<T>): T => {
const { location } = useRouterBackward<T>(r)
// @ts-ignore
return location.query
}
export const useQueryBackward = <T extends ParsedQuery>(r: RouteComponentProps<T>): T => {
// @ts-ignore
const { query } = useLocationBackward(r)
const q = useMemo(() => qs.parse(query), [query])
return q as T
}
export const useUpdateQueryBackward = <T extends ParsedQuery>(r: RouteComponentProps<T>) => {
const { history } = useRouterBackward(r)
const query = useQueryBackward<T>(r)
const updateQuery = useCallback(
(patch: Partial<T>, merge = true): void => {
const newQuery = merge ? { ...query, ...patch } : patch
const newSearch = qs.stringify(newQuery)
history.push({ search: newSearch })
},
[history, query],
)
return updateQuery
}
@iShawnWang
Copy link
Author

for react-router 4.x:

import {RouteComponentProps} from 'react-router'
import {useRouterBackward, useQueryBackward} from '@/common/hooks'

const DemoComp = (props: RouteComponentProps) => {
  const router = useRouterBackward(props)
  const query = useQueryBackward(props)
  
  return 'nice'
}

for react-router 5.x :

Just call useRouter, useLocation, useQuery function without backward suffix

@videni
Copy link

videni commented Jul 27, 2019

nice, thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment