type-route
Version:
The flexible, type safe routing library.
103 lines (88 loc) • 3 kB
text/typescript
import {
CoreRouter,
UmbrellaRouteDefCollection,
UmbrellaRoute,
RouteDefCollectionRoute,
RouterOpts,
} from "./types";
import { createRouter as coreCreateRouter, parseArgs } from "./createRouter";
import { TypeRouteError } from "./TypeRouteError";
import * as React from "react";
import { attemptScrollToTop } from "./attemptScrollToTop";
if (typeof __DEV__ === "boolean" && __DEV__) {
const [major, minor] = React.version
.split(".")
.map((value: string) => parseInt(value, 10));
if (major < 16 || (major === 16 && minor < 8)) {
throw TypeRouteError.Invalid_React_version.create(React.version);
}
}
export { defineRoute } from "./defineRoute";
export { param } from "./param";
export { createGroup } from "./createGroup";
export { noMatch } from "./noMatch";
export { preventDefaultLinkClickBehavior } from "./preventDefaultLinkClickBehavior";
export {
GetRoute as Route,
Link,
ValueSerializer,
QueryStringSerializer,
SessionOpts,
RouterOpts,
} from "./types";
type Router<TRouteDefCollection extends { [routeName: string]: any }> =
CoreRouter<TRouteDefCollection> & {
/**
* React hook for retrieving the current route.
*
* @see https://type-route.zilch.dev/api-reference/router/use-route
*/
useRoute: () => RouteDefCollectionRoute<TRouteDefCollection>;
/**
* React component which connects React to Type Route and provides the current route to the rest of the application.
*
* @see https://type-route.zilch.dev/api-reference/router/route-provider
*/
RouteProvider: (props: { children?: any }) => any;
};
type UmbrellaRouter = Router<UmbrellaRouteDefCollection>;
export function createRouter<
TRouteDefCollection extends { [routeName: string]: any }
>(routeDefs: TRouteDefCollection): Router<TRouteDefCollection>;
export function createRouter<
TRouteDefCollection extends { [routeName: string]: any }
>(
opts: RouterOpts,
routeDefs: TRouteDefCollection
): Router<TRouteDefCollection>;
export function createRouter(...args: any[]): UmbrellaRouter {
const { opts, routeDefs } = parseArgs(args);
const router = coreCreateRouter({ ...opts, scrollToTop: false }, routeDefs);
const routeContext = React.createContext<UmbrellaRoute | null>(null);
return {
...router,
RouteProvider,
useRoute,
};
function RouteProvider(props: { children?: any }) {
const [route, setRoute] = React.useState(router.session.getInitialRoute());
React.useLayoutEffect(() => router.session.listen(setRoute), []);
React.useEffect(() => {
attemptScrollToTop(route, opts.scrollToTop);
}, [route]);
return React.createElement(
routeContext.Provider,
{ value: route },
props.children
);
}
function useRoute() {
const route = React.useContext(routeContext);
if (__DEV__) {
if (route === null) {
throw TypeRouteError.App_should_be_wrapped_in_a_RouteProvider_component.create();
}
}
return route!;
}
}