Skip to content

Commit

Permalink
Add documentation comments
Browse files Browse the repository at this point in the history
  • Loading branch information
kyarik committed Dec 21, 2020
1 parent 8102aa8 commit ba5581f
Show file tree
Hide file tree
Showing 9 changed files with 172 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/components/Link/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ export interface LinkProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>,
to: string;
}

/**
* Component that is used to create internal links. It accepts a `to` prop
* specifying a path, and any other prop that an `<a>` element would accept
* (except `href`).
*/
export const Link: FC<LinkProps> = ({
to,
target,
Expand Down
5 changes: 5 additions & 0 deletions src/components/NavLink/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ import { Link, LinkProps } from '../Link';

export type NavLinkProps = LinkProps;

/**
* Behaves in the same way as `<Link>` but it adds an `active` class to the
* `className` of the rendered `<a>` element whenever the current path matches
* the path specified as the `to` prop.
*/
export const NavLink: FC<NavLinkProps> = ({ to, className, ...props }) => {
const pathname = usePathname();

Expand Down
5 changes: 5 additions & 0 deletions src/components/PreRouter/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ interface Props {
router: Router;
}

/**
* Component that is responsible for rendering the routes of your app. It
* accepts a single `router` prop, which is the `Router` object that was
* creating with `createRouter`.
*/
export const PreRouter: VFC<Props> = ({ router }) => {
return (
<RouterProvider value={router}>
Expand Down
7 changes: 7 additions & 0 deletions src/components/Redirect/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ export interface RedirectProps {
push?: boolean;
}

/**
* Component that can be used to perform an internal redirect. It accepts a
* `to` prop specifying the destination path. By default, the new destination
* will override the current entry in the history stack. If you instead want
* the new destination to be added to the stack rather than replacing the
* current enty, you can pass a `push` prop with a value of `true`.
*/
export const Redirect: VFC<RedirectProps> = ({ to, push = false }) => {
const { history } = useRouter();

Expand Down
3 changes: 3 additions & 0 deletions src/hooks/usePathname/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { useEffect, useState } from 'react';
import { useRouter } from '../../hooks/useRouter';

/**
* Returns the current location's pathname.
*/
export const usePathname = () => {
const { history } = useRouter();
const [pathname, setPathname] = useState(history.location.pathname);
Expand Down
5 changes: 5 additions & 0 deletions src/hooks/useRouteTransitionPending/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { useContext } from 'react';
import { RouteTransitionPendingContext } from '../../context/RouteTransitionPendingContext';

/**
* Returns a boolean indicating whether a route transition is pending. This is
* only applicable when you opt into route transitions by passing the
* `useTransition` option.
*/
export const useRouteTransitionPending = () => {
const routeTransitionPending = useContext(RouteTransitionPendingContext);

Expand Down
4 changes: 4 additions & 0 deletions src/hooks/useRouter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import { invariant } from 'circumspect';
import { useContext } from 'react';
import { RouterContext } from '../../context/RouterContext';

/**
* Returns the `Router` object that was specified as the `router` prop to
* `<PreRouter>`.
*/
export const useRouter = () => {
const router = useContext(RouterContext);

Expand Down
130 changes: 130 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,20 @@ export interface RouteComponentProps<
TPreloadedData = any,
TParams extends Record<string, string> = Record<string, string>
> {
/**
* The preloaded data returned by `preloadData`. If `preloadData` is not
* specified for a route, then `preloadedData` is `undefined`.
*/
preloadedData: TPreloadedData;

/**
* The values of the dynamic parameters in the `path`, if any.
*/
params: TParams;

/**
* Any matching child routes that should be rendered inside the parent route.
*/
children: ReactNode;
}

Expand All @@ -29,10 +41,34 @@ export type Route<
TPreloadedData = any,
TParams extends Record<string, string> = Record<string, string>
> = {
/**
* The path for which this route will match. Path parameters, even with
* custom regular expressions, are supported.
*/
path?: string;

/**
* The component to render for the route.
*/
component: RouteComponent<TPreloadedData, TParams>;

/**
* Function used to preload data for the route whenever it matches. This
* function is called with the route parameters and it should return the
* preloaded data in the form of a resource that the route component can
* attempt to read and if it's not ready yet, the component suspends.
*/
preloadData?: (params: TParams) => TPreloadedData;

/**
* The fallback component that will be shown while the component or data for
* the route are still loading.
*/
fallback?: ComponentType;

/**
* Children routes of the current route.
*/
routes?: Route[];
};

Expand Down Expand Up @@ -61,29 +97,123 @@ export interface RouterEntry {

export type UseTransition = () => [(callback: () => void) => void, boolean];

/**
* Specifies what type of content to preload for a path even before the
* navigation to that path occurs.
*/
export type PreloadContentOption = 'code' | 'code-and-data' | 'none';

export type RouterHistoryOption = 'browser' | 'hash' | 'memory' | ['memory', MemoryHistoryOptions];

export interface RouterOptions {
/**
* The default fallback component to use for any route that didn't specify a
* custom `fallback`. The default fallback will be shown while the component
* or data for the route are loading.
*/
defaultFallback?: ComponentType;

/**
* The error fallback component to show when an error occurs for some route,
* e.g., when the component or data for a route fails to load.
*/
errorFallback?: ComponentType<{ error: Error; retry: () => void }>;

/**
* The type of history object to use for route navigation. The history object
* is created with the [`history`
* package](https://github.com/ReactTraining/history).
*/
history?: RouterHistoryOption;

/**
* Callback that is called when an error occurs for some route, e.g., when
* the component or data for a route fails to load. This callback can be used
* to log the error information to an error reporting service.
*/
onError?: (error: Error, errorInfo: ErrorInfo) => void;

/**
* Content to preload for a link's path whenever the link is hovered.
*/
preloadOnLinkHover?: PreloadContentOption;

/**
* Content to preload for a link's path whenever the link is pressed in
* (mouse down on desktop).
*/
preloadOnLinkPressIn?: PreloadContentOption;

/**
* The `useTransition` hook exported by React. When you pass the
* `useTransition` hook, you opt into having a delay during route updates in
* order to avoid showing undesirable loading states.
*/
useTransition?: UseTransition;
}

export interface Router {
/**
* Disables the transition for the next route update. This is only applicable
* when you opt into route transitions by passing the `useTransition` option.
*/
disableNextRouteTransition: () => void;

/**
* Enables the transition for the next route update. This is only applicable
* when you opt into route transitions by passing the `useTransition` option.
*/
enableNextRouteTransition: () => void;

/**
* Returns the current router entry, which consists of the location object
* and the preloaded routes for that location.
*/
getCurrentRouterEntry: () => RouterEntry;

/**
* The history object created with the `history` package, which provides the
* primitives for route navigation.
*/
history: BrowserHistory | MemoryHistory | HashHistory;

/**
* Returns whether the transition for the next route is enabled. This is only
* applicable when you opt into route transitions by passing the
* `useTransition` option.
*/
isNextRouteTransitionEnabled: () => boolean;

/**
* The options provided to `createRouter` populated with default values for
* all options that were omitted.
*/
options: Required<RouterOptions>;

/**
* Preloads the specified `content` for the given path before the navigation
* to that path actually occurs. Note that if the specified `content` is
* already loaded or is loading for the given `path`, then this function has
* no effect.
*/
preloadBeforeNavigation: (path: string, content: PreloadContentOption) => void;

/**
* Refreshes the current router entry by preloading again the components and
* data for the current entry. Note that if the components already loaded or
* are still loading, then preloading them again will have no effect.
*/
refreshCurrentRouterEntry: () => void;

/**
* Removes the history listener that the router attached to the history
* object when it was created.
*/
removeHistoryListener: () => void;

/**
* Subscribes the given callback function to router entry changes. A cleanup
* function is returned that will unsubscribe the callback when called.
*/
subscribe: (subscriber: (routerEntry: RouterEntry) => void) => () => void;
}
8 changes: 8 additions & 0 deletions src/utils/createRouter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ import { getRouterOptionsWithDefaults } from '../getRouterOptionsWithDefaults';
import { matchRoutes } from '../matchRoutes';
import { preloadRoutes } from '../preloadRoutes';

/**
* Creates a router with the specified routes. The main properties in the
* definition of each route are the path, the function to preload the data for
* the route, and the component to render for the route. The created `Router`
* object can then be passed to the `<PreRouter>` component.
* @param routes is an array with the definition of all routes.
* @param options are the router options.
*/
export const createRouter = (routes: Route[], options: RouterOptions = {}): Router => {
const optionsWithDefaults = getRouterOptionsWithDefaults(options);
const history = createHistory(optionsWithDefaults.history);
Expand Down

0 comments on commit ba5581f

Please sign in to comment.