# @reykjavik/webtools/react-router/\* These are the [react-router (>=7)](https://reactrouter.com)-specific utilities in the `@reykjavik/webtools` package. **Contents:** - [`@reykjavik/webtools/react-router/Wait`](#reykjavikwebtoolsreact-routerwait) - [`Wait` component](#wait-component) - [Type `WaitComponent`](#type-waitcomponent) - [`@reykjavik/webtools/react-router/http`](#reykjavikwebtoolsreact-routerhttp) - [`isClientFetch`](#isclientfetch) --- ## `@reykjavik/webtools/react-router/Wait` Contains a thin wrapper around [React-Router's `Await` component](https://reactrouter.com/how-to/suspense#2-render-the-fallback-and-resolved-ui), to provide a more ergonomic API. --- ### `Wait` component It waits `for` a promise, renders a spinner `meanwhile`, and an `error` message if the promise rejects. If the awaited promise resolves to an object with a truthy `$error` property, the error will be thrown. ```tsx import type { Route } from './+types/test-page'; import { useAsyncError } from 'react-router'; import { Wait } from '@reykjavik/webtools/react-router/Wait'; export const loader = async (args: Route.LoaderArgs) => { return { document: getDocument().catch(() => ({ $error: 'Failed to load document', })), }; }; export default function TestPage(props: Route.ComponentProps) { const { document } = props.loaderData; return ( Loading document...

} error={} > {(document) => (

{document.title}

{document.text}

)}
); } // ---- const CustomError = () => { const error = useAsyncError(); const errMessage = error instanceof Error ? error.message : error; return

Error: {errMessage}

; }; ``` **Props:** - **`for`**`: Promise | T` The value you want to wait for before rendering. - **`children`**`: (data: Exclude) => ReactNode` A function to render the children when the value is resolved. (If the promise resolved to an object with a truthy `$error` property, then the `$error` is thrown and this function skipped.) - **`meanwhile`**`?: ReactNode` — (Default: `'Loading...'`) Custom loading/spinner component. - **`error`**`?: ReactNode` — (Default: `'An error occurred.'`) Custom error component if the promise is rejected or if it resolves to an object with an `$error` property. --- ### Type `WaitComponent` A function component that wraps `@reykjavik/webtools/react-router/Wait` to provide custom properties for `meanwhile` and `error` fallbacks, and/or other behaviors. You can pass a type parameter listing the "CustomProps" it accepts in addition to the base `for` and `children` props of ``. ```tsx import { Wait, WaitComponent } from '@reykjavik/webtools/react-router/Wait'; export const MyWait: WaitComponent<{ size?: 'large' | 'small' }> = ( props ) => { return ( } error={} > {props.children} ); }; export type MyWaitProps = Parameters[0]; // { // for: Promise | T; // children: (data: Exclude) => ReactNode; // // CustomProps: // size?: 'large' | 'small'; // } ``` --- ## `@reykjavik/webtools/react-router/http` Contains utilities to aid working with `loader` and `action` functions. --- ### `isClientFetch` **Syntax:** `isClientFetch(request: Request): boolean` Detects if the request is a client fetch, or an initial/full-page load. This can be used to decide whether to await the fetched data or not. ```ts import type { Route } from './+types/my-route-module'; import { isClientFetch } from '@reykjavik/webtools/react-router/deferring'; export const loader = async (args: Route.LoaderArgs) => { const document = fetchDocument(); if (!isClientFetch(args.request)) { // Make the page curl-friendly by waiting for the promise to resolve // before rendering the page, on initial load or browser reload. await document; } return { document }; }; ```