Skip to content

Commit 5ceb311

Browse files
Fix types, simplify code, use wrangler types
Co-authored-by: elithrar <elithrar@users.noreply.github.com>
1 parent 5121c5b commit 5ceb311

File tree

1 file changed

+23
-38
lines changed

1 file changed

+23
-38
lines changed

src/content/docs/d1/examples/d1-and-react-router.mdx

Lines changed: 23 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ description: Query your D1 database from a React Router application.
1111

1212
import { TabItem, Tabs, PackageManagers, WranglerConfig } from "~/components";
1313

14-
[React Router v7](https://reactrouter.com/) is a full-stack web framework for building React applications. You can query your D1 database from React Router using the [data loading](https://reactrouter.com/start/framework/data-loading) API with the `loader` function and `useLoaderData` hook.
14+
[React Router v7](https://reactrouter.com/) is a full-stack web framework for building React applications. You can query your D1 database from React Router using the [data loading](https://reactrouter.com/start/framework/data-loading) API with the `loader` function.
1515

1616
## Set up a React Router project with D1
1717

@@ -61,59 +61,44 @@ import type { Route } from "./+types/users";
6161
export async function loader({ context }: Route.LoaderArgs) {
6262
const env = context.cloudflare.env;
6363

64-
try {
65-
const { results } = await env.DB.prepare(
66-
"SELECT * FROM users LIMIT 5"
67-
).run();
68-
return { users: results };
69-
} catch (error) {
70-
return { users: [], error: "Failed to fetch users" };
71-
}
64+
const { results } = await env.DB.prepare(
65+
"SELECT * FROM users LIMIT 5"
66+
).run();
67+
return { users: results };
7268
}
7369

7470
export default function Users({ loaderData }: Route.ComponentProps) {
75-
const { users, error } = loaderData;
76-
77-
if (error) {
78-
return <div>Error: {error}</div>;
79-
}
80-
8171
return (
82-
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.8" }}>
72+
<div>
8373
<h1>Users</h1>
84-
<pre>{JSON.stringify(users, null, 2)}</pre>
74+
<pre>{JSON.stringify(loaderData.users, null, 2)}</pre>
8575
</div>
8676
);
8777
}
8878
```
8979

9080
</TabItem> </Tabs>
9181

92-
## Add type safety
82+
## Generate types
9383

94-
For full type safety, extend the `CloudflareEnvironment` interface in your Worker entry file:
84+
The React Router Cloudflare template includes a `cf-typegen` script that runs [`wrangler types`](/workers/wrangler/commands/#types) to generate an `Env` interface from your Wrangler configuration. After adding the D1 binding to your Wrangler configuration, run the script to generate types:
9585

96-
```ts title="workers/app.ts"
97-
import { createRequestHandler } from "react-router";
86+
```sh
87+
npm run cf-typegen
88+
```
9889

99-
declare global {
100-
interface CloudflareEnvironment {
101-
DB: D1Database;
102-
}
103-
}
90+
This generates a `worker-configuration.d.ts` file that includes your D1 binding:
10491

105-
const requestHandler = createRequestHandler(
106-
() => import("virtual:react-router/server-build"),
107-
import.meta.env.MODE,
108-
);
109-
110-
export default {
111-
async fetch(request, env, ctx) {
112-
return requestHandler(request, {
113-
cloudflare: { env, ctx },
114-
});
115-
},
116-
} satisfies ExportedHandler<CloudflareEnvironment>;
92+
```ts title="worker-configuration.d.ts"
93+
interface Env {
94+
DB: D1Database;
95+
}
11796
```
11897

98+
The `workers/app.ts` entry file in the template already uses this `Env` type, so your `context.cloudflare.env.DB` calls will be fully typed without any manual configuration.
99+
100+
:::note
101+
Run `npm run cf-typegen` whenever you change bindings in your Wrangler configuration to keep your types in sync.
102+
:::
103+
119104
For more information on using bindings with React Router, refer to the [React Router framework guide](/workers/framework-guides/web-apps/react-router/#use-bindings-with-react-router).

0 commit comments

Comments
 (0)