diff --git a/.changeset/violet-beds-swim.md b/.changeset/violet-beds-swim.md new file mode 100644 index 0000000000..1acd1fdaa0 --- /dev/null +++ b/.changeset/violet-beds-swim.md @@ -0,0 +1,5 @@ +--- +"react-router": minor +--- + +Stabilize `unstable_dataStrategy` diff --git a/integration/defer-loader-test.ts b/integration/defer-loader-test.ts index 252fed6b10..534716b389 100644 --- a/integration/defer-loader-test.ts +++ b/integration/defer-loader-test.ts @@ -28,9 +28,9 @@ test.describe("deferred loaders", () => { `, "app/routes/redirect.tsx": js` - import { unstable_data } from 'react-router'; + import { data } from 'react-router'; export function loader() { - return unstable_data( + return data( { food: "pizza" }, { status: 301, diff --git a/integration/single-fetch-test.ts b/integration/single-fetch-test.ts index b57d86c256..5a780a12a2 100644 --- a/integration/single-fetch-test.ts +++ b/integration/single-fetch-test.ts @@ -110,7 +110,7 @@ const files = { `, "app/routes/data-with-response.tsx": js` - import { useActionData, useLoaderData, unstable_data as data } from "react-router"; + import { useActionData, useLoaderData, data } from "react-router"; export function headers ({ actionHeaders, loaderHeaders, errorHeaders }) { if ([...actionHeaders].length > 0) { @@ -253,7 +253,7 @@ test.describe("single-fetch", () => { }); }); - test("loads proper data (via unstable_data) on single fetch loader requests", async () => { + test("loads proper data (via data()) on single fetch loader requests", async () => { let fixture = await createFixture({ files, }); @@ -280,7 +280,7 @@ test.describe("single-fetch", () => { }); }); - test("loads proper data (via unstable_data) on single fetch action requests", async () => { + test("loads proper data (via data()) on single fetch action requests", async () => { let fixture = await createFixture({ files, }); @@ -505,28 +505,28 @@ test.describe("single-fetch", () => { expect(urls).toEqual([]); }); - test("does not revalidate on 4xx/5xx action responses (via unstable_data)", async ({ + test("does not revalidate on 4xx/5xx action responses (via data())", async ({ page, }) => { let fixture = await createFixture({ files: { ...files, "app/routes/action.tsx": js` - import { Form, Link, useActionData, useLoaderData, useNavigation, unstable_data } from 'react-router'; + import { Form, Link, useActionData, useLoaderData, useNavigation, data } from 'react-router'; export async function action({ request }) { let fd = await request.formData(); if (fd.get('throw') === "5xx") { - throw unstable_data("Thrown 500", { status: 500 }); + throw data("Thrown 500", { status: 500 }); } if (fd.get('throw') === "4xx") { - throw unstable_data("Thrown 400", { status: 400 }); + throw data("Thrown 400", { status: 400 }); } if (fd.get('return') === "5xx") { - return unstable_data("Returned 500", { status: 500 }); + return data("Returned 500", { status: 500 }); } if (fd.get('return') === "4xx") { - return unstable_data("Returned 400", { status: 400 }); + return data("Returned 400", { status: 400 }); } return null; } diff --git a/packages/react-router/__tests__/data-memory-router-test.tsx b/packages/react-router/__tests__/data-memory-router-test.tsx index 3375d47fde..67bb418f18 100644 --- a/packages/react-router/__tests__/data-memory-router-test.tsx +++ b/packages/react-router/__tests__/data-memory-router-test.tsx @@ -3292,7 +3292,7 @@ describe("createMemoryRouter", () => { /> ), - { initialEntries: ["/foo"], unstable_dataStrategy: urlDataStrategy } + { initialEntries: ["/foo"], dataStrategy: urlDataStrategy } ); let { container } = render(); diff --git a/packages/react-router/__tests__/router/ssr-test.ts b/packages/react-router/__tests__/router/ssr-test.ts index 29263b984c..fb58a9a16d 100644 --- a/packages/react-router/__tests__/router/ssr-test.ts +++ b/packages/react-router/__tests__/router/ssr-test.ts @@ -1403,7 +1403,7 @@ describe("ssr", () => { let { query } = createStaticHandler(SSR_ROUTES); let context = await query(createRequest("/custom"), { - unstable_dataStrategy: urlDataStrategy, + dataStrategy: urlDataStrategy, }); expect(context).toMatchObject({ actionData: null, @@ -2251,7 +2251,7 @@ describe("ssr", () => { let data; data = await queryRoute(createRequest("/custom"), { - unstable_dataStrategy: urlDataStrategy, + dataStrategy: urlDataStrategy, }); expect(data).toBeInstanceOf(URLSearchParams); expect((data as URLSearchParams).get("foo")).toBe("bar"); diff --git a/packages/react-router/__tests__/router/utils/data-router-setup.ts b/packages/react-router/__tests__/router/utils/data-router-setup.ts index a5724065d7..d0532819fb 100644 --- a/packages/react-router/__tests__/router/utils/data-router-setup.ts +++ b/packages/react-router/__tests__/router/utils/data-router-setup.ts @@ -339,7 +339,7 @@ export function setup({ routes: enhanceRoutes(routes), hydrationData, window: testWindow, - unstable_dataStrategy: dataStrategy, + dataStrategy: dataStrategy, }); let fetcherData = getFetcherData(currentRouter); diff --git a/packages/react-router/index.ts b/packages/react-router/index.ts index 1cde18d67b..993dc1f048 100644 --- a/packages/react-router/index.ts +++ b/packages/react-router/index.ts @@ -23,10 +23,10 @@ export type { export type { ActionFunction, ActionFunctionArgs, - DataStrategyFunction as unstable_DataStrategyFunction, - DataStrategyFunctionArgs as unstable_DataStrategyFunctionArgs, - DataStrategyMatch as unstable_DataStrategyMatch, - DataStrategyResult as unstable_DataStrategyResult, + DataStrategyFunction, + DataStrategyFunctionArgs, + DataStrategyMatch, + DataStrategyResult, DataWithResponseInit as UNSAFE_DataWithResponseInit, ErrorResponse, FormEncType, @@ -58,7 +58,7 @@ export { IDLE_BLOCKER, } from "./lib/router/router"; export { - data as unstable_data, + data, generatePath, isRouteErrorResponse, json, diff --git a/packages/react-router/lib/components.tsx b/packages/react-router/lib/components.tsx index 2dddec9e40..fc5c3f5462 100644 --- a/packages/react-router/lib/components.tsx +++ b/packages/react-router/lib/components.tsx @@ -144,7 +144,7 @@ export function createMemoryRouter( hydrationData?: HydrationState; initialEntries?: InitialEntry[]; initialIndex?: number; - unstable_dataStrategy?: DataStrategyFunction; + dataStrategy?: DataStrategyFunction; patchRoutesOnNavigation?: PatchRoutesOnNavigationFunction; } ): RemixRouter { @@ -158,7 +158,7 @@ export function createMemoryRouter( hydrationData: opts?.hydrationData, routes, mapRouteProperties, - unstable_dataStrategy: opts?.unstable_dataStrategy, + dataStrategy: opts?.dataStrategy, patchRoutesOnNavigation: opts?.patchRoutesOnNavigation, }).initialize(); } diff --git a/packages/react-router/lib/dom-export/hydrated-router.tsx b/packages/react-router/lib/dom-export/hydrated-router.tsx index bd7b072e5b..35e451c8c5 100644 --- a/packages/react-router/lib/dom-export/hydrated-router.tsx +++ b/packages/react-router/lib/dom-export/hydrated-router.tsx @@ -169,7 +169,7 @@ function createHydratedRouter(): RemixRouter { basename: ssrInfo.context.basename, hydrationData, mapRouteProperties, - unstable_dataStrategy: getSingleFetchDataStrategy( + dataStrategy: getSingleFetchDataStrategy( ssrInfo.manifest, ssrInfo.routeModules, () => router diff --git a/packages/react-router/lib/dom/lib.tsx b/packages/react-router/lib/dom/lib.tsx index c6a280b2f4..f036ace794 100644 --- a/packages/react-router/lib/dom/lib.tsx +++ b/packages/react-router/lib/dom/lib.tsx @@ -122,7 +122,7 @@ interface DOMRouterOpts { basename?: string; future?: Partial; hydrationData?: HydrationState; - unstable_dataStrategy?: DataStrategyFunction; + dataStrategy?: DataStrategyFunction; patchRoutesOnNavigation?: PatchRoutesOnNavigationFunction; window?: Window; } @@ -141,7 +141,7 @@ export function createBrowserRouter( hydrationData: opts?.hydrationData || parseHydrationData(), routes, mapRouteProperties, - unstable_dataStrategy: opts?.unstable_dataStrategy, + dataStrategy: opts?.dataStrategy, patchRoutesOnNavigation: opts?.patchRoutesOnNavigation, window: opts?.window, }).initialize(); @@ -161,7 +161,7 @@ export function createHashRouter( hydrationData: opts?.hydrationData || parseHydrationData(), routes, mapRouteProperties, - unstable_dataStrategy: opts?.unstable_dataStrategy, + dataStrategy: opts?.dataStrategy, patchRoutesOnNavigation: opts?.patchRoutesOnNavigation, window: opts?.window, }).initialize(); diff --git a/packages/react-router/lib/dom/ssr/single-fetch.tsx b/packages/react-router/lib/dom/ssr/single-fetch.tsx index 7b93b75105..1a9d4c8f9e 100644 --- a/packages/react-router/lib/dom/ssr/single-fetch.tsx +++ b/packages/react-router/lib/dom/ssr/single-fetch.tsx @@ -184,7 +184,7 @@ async function singleFetchActionStrategy( return { [actionMatch.route.id]: result }; } - // For non-responses, proxy along the statusCode via unstable_data() + // For non-responses, proxy along the statusCode via data() // (most notably for skipping action error revalidation) return { [actionMatch.route.id]: { diff --git a/packages/react-router/lib/router/router.ts b/packages/react-router/lib/router/router.ts index 202ae3090a..c016e0d7db 100644 --- a/packages/react-router/lib/router/router.ts +++ b/packages/react-router/lib/router/router.ts @@ -369,8 +369,8 @@ export interface RouterInit { future?: Partial; hydrationData?: HydrationState; window?: Window; + dataStrategy?: DataStrategyFunction; patchRoutesOnNavigation?: AgnosticPatchRoutesOnNavigationFunction; - unstable_dataStrategy?: DataStrategyFunction; } /** @@ -399,7 +399,7 @@ export interface StaticHandler { opts?: { requestContext?: unknown; skipLoaderErrorBubbling?: boolean; - unstable_dataStrategy?: DataStrategyFunction; + dataStrategy?: DataStrategyFunction; } ): Promise; queryRoute( @@ -407,7 +407,7 @@ export interface StaticHandler { opts?: { routeId?: string; requestContext?: unknown; - unstable_dataStrategy?: DataStrategyFunction; + dataStrategy?: DataStrategyFunction; } ): Promise; } @@ -808,7 +808,7 @@ export function createRouter(init: RouterInit): Router { ); let inFlightDataRoutes: AgnosticDataRouteObject[] | undefined; let basename = init.basename || "/"; - let dataStrategyImpl = init.unstable_dataStrategy || defaultDataStrategy; + let dataStrategyImpl = init.dataStrategy || defaultDataStrategy; let patchRoutesOnNavigationImpl = init.patchRoutesOnNavigation; // Config driven behavior flags @@ -3410,11 +3410,11 @@ export function createStaticHandler( { requestContext, skipLoaderErrorBubbling, - unstable_dataStrategy, + dataStrategy, }: { requestContext?: unknown; skipLoaderErrorBubbling?: boolean; - unstable_dataStrategy?: DataStrategyFunction; + dataStrategy?: DataStrategyFunction; } = {} ): Promise { let url = new URL(request.url); @@ -3464,7 +3464,7 @@ export function createStaticHandler( location, matches, requestContext, - unstable_dataStrategy || null, + dataStrategy || null, skipLoaderErrorBubbling === true, null ); @@ -3509,11 +3509,11 @@ export function createStaticHandler( { routeId, requestContext, - unstable_dataStrategy, + dataStrategy, }: { requestContext?: unknown; routeId?: string; - unstable_dataStrategy?: DataStrategyFunction; + dataStrategy?: DataStrategyFunction; } = {} ): Promise { let url = new URL(request.url); @@ -3547,7 +3547,7 @@ export function createStaticHandler( location, matches, requestContext, - unstable_dataStrategy || null, + dataStrategy || null, false, match ); @@ -3582,7 +3582,7 @@ export function createStaticHandler( location: Location, matches: AgnosticDataRouteMatch[], requestContext: unknown, - unstable_dataStrategy: DataStrategyFunction | null, + dataStrategy: DataStrategyFunction | null, skipLoaderErrorBubbling: boolean, routeMatch: AgnosticDataRouteMatch | null ): Promise | Response> { @@ -3598,7 +3598,7 @@ export function createStaticHandler( matches, routeMatch || getTargetMatch(matches, location), requestContext, - unstable_dataStrategy, + dataStrategy, skipLoaderErrorBubbling, routeMatch != null ); @@ -3609,7 +3609,7 @@ export function createStaticHandler( request, matches, requestContext, - unstable_dataStrategy, + dataStrategy, skipLoaderErrorBubbling, routeMatch ); @@ -3644,7 +3644,7 @@ export function createStaticHandler( matches: AgnosticDataRouteMatch[], actionMatch: AgnosticDataRouteMatch, requestContext: unknown, - unstable_dataStrategy: DataStrategyFunction | null, + dataStrategy: DataStrategyFunction | null, skipLoaderErrorBubbling: boolean, isRouteRequest: boolean ): Promise | Response> { @@ -3671,7 +3671,7 @@ export function createStaticHandler( matches, isRouteRequest, requestContext, - unstable_dataStrategy + dataStrategy ); result = results[actionMatch.route.id]; @@ -3731,7 +3731,7 @@ export function createStaticHandler( loaderRequest, matches, requestContext, - unstable_dataStrategy, + dataStrategy, skipLoaderErrorBubbling, null, [boundaryMatch.route.id, result] @@ -3756,7 +3756,7 @@ export function createStaticHandler( loaderRequest, matches, requestContext, - unstable_dataStrategy, + dataStrategy, skipLoaderErrorBubbling, null ); @@ -3778,7 +3778,7 @@ export function createStaticHandler( request: Request, matches: AgnosticDataRouteMatch[], requestContext: unknown, - unstable_dataStrategy: DataStrategyFunction | null, + dataStrategy: DataStrategyFunction | null, skipLoaderErrorBubbling: boolean, routeMatch: AgnosticDataRouteMatch | null, pendingActionResult?: PendingActionResult @@ -3840,7 +3840,7 @@ export function createStaticHandler( matches, isRouteRequest, requestContext, - unstable_dataStrategy + dataStrategy ); if (request.signal.aborted) { @@ -3880,10 +3880,10 @@ export function createStaticHandler( matches: AgnosticDataRouteMatch[], isRouteRequest: boolean, requestContext: unknown, - unstable_dataStrategy: DataStrategyFunction | null + dataStrategy: DataStrategyFunction | null ): Promise> { let results = await callDataStrategyImpl( - unstable_dataStrategy || defaultDataStrategy, + dataStrategy || defaultDataStrategy, type, null, request, @@ -4867,7 +4867,7 @@ async function convertDataStrategyResultToDataResult( }; } - // Convert thrown unstable_data() to ErrorResponse instances + // Convert thrown data() to ErrorResponse instances result = new ErrorResponseImpl( result.init?.status || 500, undefined, diff --git a/packages/react-router/lib/server-runtime/single-fetch.ts b/packages/react-router/lib/server-runtime/single-fetch.ts index 54e216fb0f..246aa0e124 100644 --- a/packages/react-router/lib/server-runtime/single-fetch.ts +++ b/packages/react-router/lib/server-runtime/single-fetch.ts @@ -84,7 +84,7 @@ export async function singleFetchAction( let result = await staticHandler.query(handlerRequest, { requestContext: loadContext, skipLoaderErrorBubbling: true, - unstable_dataStrategy: getSingleFetchDataStrategy({ + dataStrategy: getSingleFetchDataStrategy({ isActionDataRequest: true, }), }); @@ -172,7 +172,7 @@ export async function singleFetchLoaders( let result = await staticHandler.query(handlerRequest, { requestContext: loadContext, skipLoaderErrorBubbling: true, - unstable_dataStrategy: getSingleFetchDataStrategy({ + dataStrategy: getSingleFetchDataStrategy({ loadRouteIds, }), });