@@ -482,6 +482,27 @@ implementations.forEach((implementation) => {
482
482
path: "no-revalidate-server-action",
483
483
lazy: () => import("./routes/no-revalidate-server-action/home"),
484
484
},
485
+ {
486
+ id: "await-component",
487
+ path: "await-component",
488
+ children: [
489
+ {
490
+ id: "await-component.home",
491
+ index: true,
492
+ lazy: () => import("./routes/await-component/home"),
493
+ },
494
+ {
495
+ id: "await-component.reject",
496
+ path: "reject",
497
+ lazy: () => import("./routes/await-component/reject"),
498
+ },
499
+ {
500
+ id: "await-component.api",
501
+ path: "api",
502
+ lazy: () => import("./routes/await-component/api"),
503
+ }
504
+ ]
505
+ }
485
506
],
486
507
},
487
508
] satisfies RSCRouteConfig;
@@ -903,7 +924,6 @@ implementations.forEach((implementation) => {
903
924
import { Counter } from "./home.client";
904
925
905
926
export default function HomeRoute(props) {
906
- console.log({props});
907
927
return (
908
928
<div>
909
929
<form action={redirectAction}>
@@ -1155,7 +1175,7 @@ implementations.forEach((implementation) => {
1155
1175
import ClientHomeRoute from "./home.client";
1156
1176
1157
1177
export function loader() {
1158
- console.log("loader ");
1178
+ console.log("THIS SHOULD NOT BE LOGGED!!! ");
1159
1179
}
1160
1180
1161
1181
export default function HomeRoute() {
@@ -1184,6 +1204,90 @@ implementations.forEach((implementation) => {
1184
1204
);
1185
1205
}
1186
1206
` ,
1207
+
1208
+ "src/routes/await-component/events.ts" : js `
1209
+ import EventEmitter from 'node:events'
1210
+
1211
+ export const events = new EventEmitter();
1212
+ ` ,
1213
+ "src/routes/await-component/api.ts" : js `
1214
+ import { events } from "./events";
1215
+ export async function action({ request }) {
1216
+ const event = await request.text()
1217
+ events.emit(event);
1218
+ return Response.json(event);
1219
+ }
1220
+ ` ,
1221
+ "src/routes/await-component/client.tsx" : js `
1222
+ "use client";
1223
+ import { useAsyncError, useAsyncValue } from "react-router";
1224
+
1225
+ export function ClientValue() {
1226
+ const value = useAsyncValue();
1227
+ return <div data-resolved>{value}</div>;
1228
+ }
1229
+
1230
+ export function ClientError() {
1231
+ const error = useAsyncError();
1232
+ return <div data-rejected>{error.message}</div>;
1233
+ }
1234
+ ` ,
1235
+ "src/routes/await-component/home.tsx" : js `
1236
+ import { Suspense } from "react";
1237
+ import { Await } from "react-router";
1238
+
1239
+ import { ClientValue } from "./client";
1240
+ import { events } from "./events";
1241
+
1242
+ export default function AwaitResolveTest() {
1243
+ const promise = new Promise(resolve => {
1244
+ events.on("resolve", () => {
1245
+ resolve("Async Data");
1246
+ });
1247
+ });
1248
+
1249
+ return (
1250
+ <>
1251
+ <Suspense fallback={<p data-fallback>Loading...</p>}>
1252
+ <Await resolve={promise}>
1253
+ <ClientValue />
1254
+ </Await>
1255
+ </Suspense>
1256
+ {Array.from({ length: 100 }, (_, i) => (
1257
+ <p key={i}>Item {i}</p>
1258
+ ))}
1259
+ </>
1260
+ );
1261
+ }
1262
+ ` ,
1263
+ "src/routes/await-component/reject.tsx" : js `
1264
+ import { Suspense } from "react";
1265
+ import { Await } from "react-router";
1266
+
1267
+ import { ClientError } from "./client";
1268
+ import { events } from "./events";
1269
+
1270
+ export default function AwaitRejectTest() {
1271
+ const promise = new Promise((_, reject) => {
1272
+ events.on("reject", () => {
1273
+ reject(new Error("Async Error"));
1274
+ });
1275
+ });
1276
+
1277
+ return (
1278
+ <>
1279
+ <Suspense fallback={<p data-fallback>Loading...</p>}>
1280
+ <Await resolve={promise} errorElement={<ClientError />}>
1281
+ {(data) => (<p data-resolved>{data}</p>)}
1282
+ </Await>
1283
+ </Suspense>
1284
+ {Array.from({ length: 100 }, (_, i) => (
1285
+ <p key={i}>Item {i}</p>
1286
+ ))}
1287
+ </>
1288
+ );
1289
+ }
1290
+ ` ,
1187
1291
} ,
1188
1292
} ) ;
1189
1293
} ) ;
@@ -1432,6 +1536,36 @@ implementations.forEach((implementation) => {
1432
1536
await page . goto ( `http://localhost:${ port } /resource-error-handling/` ) ;
1433
1537
validateRSCHtml ( await page . content ( ) ) ;
1434
1538
} ) ;
1539
+
1540
+ test ( "Supports Await component resolve" , async ( { page } ) => {
1541
+ await page . goto ( `http://localhost:${ port } /await-component` , {
1542
+ waitUntil : "commit" ,
1543
+ } ) ;
1544
+ await page . waitForSelector ( "[data-fallback]" ) ;
1545
+ await fetch ( `http://localhost:${ port } /await-component/api` , {
1546
+ method : "POST" ,
1547
+ headers : { "Content-Type" : "text/plain" } ,
1548
+ body : "resolve" ,
1549
+ } ) ;
1550
+ const resolved = await page . waitForSelector ( "[data-resolved]" ) ;
1551
+ expect ( await resolved . innerText ( ) ) . toContain ( "Async Data" ) ;
1552
+ } ) ;
1553
+
1554
+ test ( "Supports Await component rejection" , async ( { page } ) => {
1555
+ await page . goto ( `http://localhost:${ port } /await-component/reject` , {
1556
+ waitUntil : "commit" ,
1557
+ } ) ;
1558
+ await page . waitForSelector ( "[data-fallback]" ) ;
1559
+ await fetch ( `http://localhost:${ port } /await-component/api` , {
1560
+ method : "POST" ,
1561
+ headers : { "Content-Type" : "text/plain" } ,
1562
+ body : "reject" ,
1563
+ } ) ;
1564
+ const rejected = await page . waitForSelector ( "[data-rejected]" ) ;
1565
+ expect ( await rejected . innerText ( ) ) . toContain (
1566
+ "An error occurred in the Server Components render." ,
1567
+ ) ;
1568
+ } ) ;
1435
1569
} ) ;
1436
1570
1437
1571
test . describe ( "Server Actions" , ( ) => {
0 commit comments