diff --git a/src/index.tsx b/src/index.tsx index 354ce1d..a4531ae 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -2,18 +2,15 @@ import * as pathToRegexp from "path-to-regexp"; import * as React from "react"; import { Context } from "@blakeembrey/react-location"; -/** - * Use context to communicate the route params. - */ -export interface Route

{ - params: P; - pathname: string; -} - /** * Internal context for nested route matching. */ -export const RouteContext = React.createContext(undefined); +const RouteContext = React.createContext< + | { + pathname: string; + } + | undefined +>(undefined); /** * Use pathname from context (or fallback on global URL). @@ -21,9 +18,9 @@ export const RouteContext = React.createContext(undefined); export const usePathname = () => { const location = React.useContext(Context); const [pathname, setPathname] = React.useState(location.url.pathname); - React.useLayoutEffect(() => - location.onChange(() => setPathname(location.url.pathname)) - ); + React.useLayoutEffect(() => { + return location.onChange(() => setPathname(location.url.pathname)); + }); const route = React.useContext(RouteContext); return route ? route.pathname : pathname; }; @@ -54,6 +51,16 @@ export function useCompile

( ); } +/** + * Standard options for `pathToRegexp.match`. + */ +export interface MatchOptions { + sensitive?: boolean; + start?: boolean; + end?: boolean; + strict?: boolean; +} + /** * React hook for matching URLs. */ @@ -86,16 +93,6 @@ export type RouteComponent

= React.ComponentType<{ params: P; }>; -/** - * Standard options for `pathToRegexp.match`. - */ -export interface MatchOptions { - sensitive?: boolean; - start?: boolean; - end?: boolean; - strict?: boolean; -} - /** * Route props accept a path, options and a function to render on match. */ @@ -125,30 +122,25 @@ function toMatchOptions( /** * Conditionally renders `children` when the path matches the active URL. */ -export function Route

({ - path = "", - start, - end, - sensitive, - strict, - component, -}: RouteProps

) { +export function Route

(props: RouteProps

) { const pathname = usePathname(); - const match = useMatch

(path, { start, end, sensitive, strict }); + const match = useMatch

(props.path || "", props); const result = React.useMemo(() => match(pathname), [match, pathname]); - return result ? : null; + return result ? : null; } /** * Render the body of a `` component. */ -function ShowRoute

(props: { +function Output

(props: { component: RouteComponent

; result: pathToRegexp.MatchResult

; }) { - const { component: Component, result: match } = props; + const { + component: Component, + result: { params, index, path }, + } = props; const pathname = usePathname(); - const { params, index, path } = match; const route = React.useMemo( () => ({ pathname: nestedPathname(pathname, index, path), @@ -172,18 +164,10 @@ export interface SwitchProps { children: Array, typeof Route>>; } -/** - * Renders `null` as the default fallback when `` does not match. - */ -export const FallbackComponent = () => null; - /** * Component for matching and rendering the first `` of children. */ -export function Switch({ - children, - fallback: Fallback = FallbackComponent, -}: SwitchProps) { +export function Switch({ children, fallback: Fallback }: SwitchProps) { const pathname = usePathname(); const childRoutes = React.useMemo( @@ -205,10 +189,10 @@ export function Switch({ return React.useMemo(() => { for (const { match, component } of childRoutes) { const result = match(pathname); - if (result) return ; + if (result) return ; } - return ; + return Fallback ? : null; }, [pathname, childRoutes]); }