---
applyTo: "web/app/routes/**/*.tsx"
---
## React Router


- You are using the latest version of React Router (v7).
- Always include the suffix `Page` when naming the default export of a route.
- The primary export in a routes file should specify `loaderData` like `export default function RouteNamePage({ loaderData }: Route.ComponentProps)`. `loaderData` is the return value from `clientLoader`.
- Use `href("/products/:id", { id: "abc123" })` to generate a url path for a route managed by the application.
  - Look at [routes.ts](mdc:web/app/routes.ts) to determine what routes and path parameters exist.
- Use `export async function clientLoader(loaderArgs: Route.ClientLoaderArgs)` to define a `clientLoader` on a route.
- Do not define `Route.*` types, these are autogenerated and can be imported from `import type { Route } from "./+types/routeFileName"`
- If URL parameters or query string values need to be checked before rendering the page, do this in a `clientLoader` and not in a `useEffect`
- Never worry about generating types using `pnpm`
- Use [`<AllMeta />`](web/app/components/shared/AllMeta.tsx) instead of MetaFunction or individual `<meta />` tags
- Use the following pattern to reference query string values (i.e. `?theQueryStringParam=value`)

```typescript
const [searchParams, _setSearchParams] = useSearchParams()
// searchParams contains the value of all query string parameters
const queryStringValue = searchParams.get("theQueryStringParam")
```

### Loading Mock Data

Don't load mock data in the component function with `useEffect`. Instead, load data in a `clientLoader`:

```typescript
// in mock.ts
export async function getServerData(options: any) {
  // ...
}

// in web/app/routes/**/*.ts
export async function clientLoader(loaderArgs: Route.ClientLoaderArgs) {
  // no error reporting is needed, this will be handled by the `getServerData`
  // mock loading functions should return result in a `data` key
  const { data } = await getServerData({
    /* ... */
  });

  // the return result here is available in `loaderData`
  return data;
}
```

### How to Use `clientLoader`

- `export async function clientLoader(loaderArgs: Route.ClientLoaderArgs) {`
- Load any server data required for page load here, not in the component function.
- Use `return redirect(href("/the/url"))` to redirect users
- Use [getQueryParam](web/app/lib/utils.ts) to get query string variables
- `throw new Response` if you need to mimic a 400, 500, etc error
- `loaderArgs` and all sub-objects are all fully typed
- `loaderArgs.params.id` to get URL parameters

### Loading Backend Data

- `~/configuration/client` re-exports all types and functions from `client/*`. Import from `~/configuration/client` instead of anything you find in the `client/` folder/package.
- For each API endpoint, there's a fully typed async function that can be used to call it. Never attempt to call an API endpoint directly.
  - Do not generate types for API parameters or responses. Reference the autogenerated types that are re-exported in `~/configuration/client`
  - For instance, the `getSignedUrl` function in [web/client/sdk.gen.ts] has a `SignedUrlResponse` type in [web/client/types.gen.ts]
  - This same type is used in the function signature, i.e. `type SignedUrlResponse = Awaited<ReturnType<typeof getSignedUrl>>["data"]`

- When using an import from `~/configuration/client`:
  - use `body:` for request params
  - always `const { data, error } = await theCall()`

`clientLoader` can only be used on initial page load within a route. If you need to load additional server data on component mount:

```tsx
import { useQuery } from "@tanstack/react-query"
import {
  // these options correspond to the server route
  createCheckoutSessionOptions,
  publicClient,
} from "~/configuration/client"

function TheComponent() {
  const { data, error } = useQuery({
    enabled: open,
    ...createCheckoutSessionOptions({
      // or `client` if authenticated
      client: publicClient,
      body: { /* API parameters here */ },
    }),
  })

  // remember to display errors by checking `error`
}
```
