Skip to content

Commit

Permalink
Move defineClientLoader/defineClientAction to react package (#9404)
Browse files Browse the repository at this point in the history
  • Loading branch information
brophdawg11 authored May 9, 2024
1 parent 62db2d7 commit 50a4cec
Show file tree
Hide file tree
Showing 15 changed files with 98 additions and 53 deletions.
12 changes: 8 additions & 4 deletions .changeset/rotten-geckos-yawn.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,18 @@ You can return custom responses via the `json`/`defer` utilities, but doing so w
let loader1 = () => {
return { a: 1, b: new Date() };
};
let data1 = useLoaderData<typeof loader1>();
// ^? {a: number, b: Date}
function Component() {
let data1 = useLoaderData<typeof loader1>();
// ^? {a: number, b: Date}
}

let loader2 = () => {
return json({ a: 1, b: new Date() }); // this opts-out of turbo-stream
};
let data2 = useLoaderData<typeof loader2>();
// ^? JsonifyObject<{a: number, b: Date}> which is really {a: number, b: string}
function Component2() {
let data2 = useLoaderData<typeof loader2>();
// ^? JsonifyObject<{a: number, b: Date}> which is really {a: number, b: string}
}
```

You can also continue to return totally custom responses with `Response` though this continues to be outside of the typesystem since the built-in `Response` type is not generic
6 changes: 6 additions & 0 deletions .changeset/sharp-bags-call.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@remix-run/react": patch
"@remix-run/server-runtime": patch
---

[REMOVE] Move defineClientLoader/defineClientAction to @remix-run/react package
12 changes: 8 additions & 4 deletions packages/remix-cloudflare/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,18 @@
let loader1 = () => {
return { a: 1, b: new Date() };
};
let data1 = useLoaderData<typeof loader1>();
// ^? {a: number, b: Date}
function Component() {
let data1 = useLoaderData<typeof loader1>();
// ^? {a: number, b: Date}
}
let loader2 = () => {
return json({ a: 1, b: new Date() }); // this opts-out of turbo-stream
};
let data2 = useLoaderData<typeof loader2>();
// ^? JsonifyObject<{a: number, b: Date}> which is really {a: number, b: string}
function Component2() {
let data2 = useLoaderData<typeof loader2>();
// ^? JsonifyObject<{a: number, b: Date}> which is really {a: number, b: string}
}
```

You can also continue to return totally custom responses with `Response` though this continues to be outside of the typesystem since the built-in `Response` type is not generic
Expand Down
2 changes: 0 additions & 2 deletions packages/remix-cloudflare/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ export {
createRequestHandler,
createSession,
unstable_defineLoader,
unstable_defineClientLoader,
unstable_defineAction,
unstable_defineClientAction,
defer,
broadcastDevReady,
logDevReady,
Expand Down
12 changes: 8 additions & 4 deletions packages/remix-deno/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,18 @@
let loader1 = () => {
return { a: 1, b: new Date() };
};
let data1 = useLoaderData<typeof loader1>();
// ^? {a: number, b: Date}
function Component() {
let data1 = useLoaderData<typeof loader1>();
// ^? {a: number, b: Date}
}
let loader2 = () => {
return json({ a: 1, b: new Date() }); // this opts-out of turbo-stream
};
let data2 = useLoaderData<typeof loader2>();
// ^? JsonifyObject<{a: number, b: Date}> which is really {a: number, b: string}
function Component2() {
let data2 = useLoaderData<typeof loader2>();
// ^? JsonifyObject<{a: number, b: Date}> which is really {a: number, b: string}
}
```

You can also continue to return totally custom responses with `Response` though this continues to be outside of the typesystem since the built-in `Response` type is not generic
Expand Down
2 changes: 0 additions & 2 deletions packages/remix-deno/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ export {
unstable_composeUploadHandlers,
unstable_createMemoryUploadHandler,
unstable_defineAction,
unstable_defineClientAction,
unstable_defineClientLoader,
unstable_defineLoader,
unstable_parseMultipartFormData,
} from "@remix-run/server-runtime";
Expand Down
12 changes: 8 additions & 4 deletions packages/remix-node/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,18 @@
let loader1 = () => {
return { a: 1, b: new Date() };
};
let data1 = useLoaderData<typeof loader1>();
// ^? {a: number, b: Date}
function Component() {
let data1 = useLoaderData<typeof loader1>();
// ^? {a: number, b: Date}
}
let loader2 = () => {
return json({ a: 1, b: new Date() }); // this opts-out of turbo-stream
};
let data2 = useLoaderData<typeof loader2>();
// ^? JsonifyObject<{a: number, b: Date}> which is really {a: number, b: string}
function Component2() {
let data2 = useLoaderData<typeof loader2>();
// ^? JsonifyObject<{a: number, b: Date}> which is really {a: number, b: string}
}
```

You can also continue to return totally custom responses with `Response` though this continues to be outside of the typesystem since the built-in `Response` type is not generic
Expand Down
2 changes: 0 additions & 2 deletions packages/remix-node/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ export {
createRequestHandler,
createSession,
unstable_defineLoader,
unstable_defineClientLoader,
unstable_defineAction,
unstable_defineClientAction,
defer,
broadcastDevReady,
logDevReady,
Expand Down
12 changes: 8 additions & 4 deletions packages/remix-react/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,18 @@
let loader1 = () => {
return { a: 1, b: new Date() };
};
let data1 = useLoaderData<typeof loader1>();
// ^? {a: number, b: Date}
function Component() {
let data1 = useLoaderData<typeof loader1>();
// ^? {a: number, b: Date}
}

let loader2 = () => {
return json({ a: 1, b: new Date() }); // this opts-out of turbo-stream
};
let data2 = useLoaderData<typeof loader2>();
// ^? JsonifyObject<{a: number, b: Date}> which is really {a: number, b: string}
function Component2() {
let data2 = useLoaderData<typeof loader2>();
// ^? JsonifyObject<{a: number, b: Date}> which is really {a: number, b: string}
}
```

You can also continue to return totally custom responses with `Response` though this continues to be outside of the typesystem since the built-in `Response` type is not generic
Expand Down
16 changes: 13 additions & 3 deletions packages/remix-react/future/single-fetch.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import type { MetaArgs, UIMatch, UNSAFE_MetaMatch } from "@remix-run/react";
import type {
MetaArgs,
UIMatch,
UNSAFE_MetaMatch,
unstable_ClientLoader as ClientLoader,
unstable_ClientAction as ClientAction,
} from "@remix-run/react";
import type {
unstable_Loader as Loader,
unstable_Action as Action,
Expand All @@ -10,9 +16,13 @@ import type {
} from "react-router-dom";

declare module "@remix-run/react" {
export function useLoaderData<T extends Loader>(): Serialize<T>;
export function useLoaderData<
T extends Loader | ClientLoader
>(): T extends Loader ? Serialize<T> : Awaited<ReturnType<T>>;

export function useActionData<T extends Action>(): Serialize<T> | undefined;
export function useActionData<T extends Action | ClientAction>():
| (T extends Action ? Serialize<T> : Awaited<ReturnType<T>>)
| undefined;

export function useRouteLoaderData<T extends Loader>(
routeId: string
Expand Down
8 changes: 8 additions & 0 deletions packages/remix-react/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,14 @@ export { ScrollRestoration } from "./scroll-restoration";

export type { RemixServerProps } from "./server";
export { RemixServer } from "./server";
export type {
ClientAction as unstable_ClientAction,
ClientLoader as unstable_ClientLoader,
} from "./single-fetch";
export {
defineClientAction as unstable_defineClientAction,
defineClientLoader as unstable_defineClientLoader,
} from "./single-fetch";

export type {
FutureConfig as UNSAFE_FutureConfig,
Expand Down
22 changes: 22 additions & 0 deletions packages/remix-react/single-fetch.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import * as React from "react";
import type {
ActionFunctionArgs as RRActionArgs,
LoaderFunctionArgs as RRLoaderArgs,
unstable_DataStrategyFunction as DataStrategyFunction,
unstable_HandlerResult as HandlerResult,
} from "@remix-run/router";
Expand All @@ -10,6 +12,9 @@ import {
import type {
UNSAFE_SingleFetchResult as SingleFetchResult,
UNSAFE_SingleFetchResults as SingleFetchResults,
unstable_Action,
unstable_Loader,
unstable_Serialize,
} from "@remix-run/server-runtime";
import { UNSAFE_SingleFetchRedirectSymbol as SingleFetchRedirectSymbol } from "@remix-run/server-runtime";
import type {
Expand All @@ -24,6 +29,23 @@ import { escapeHtml } from "./markup";
import type { RouteModules } from "./routeModules";
import invariant from "./invariant";

// clientLoader
type ClientLoaderArgs = RRLoaderArgs<undefined> & {
serverLoader: <T extends unstable_Loader>() => Promise<unstable_Serialize<T>>;
};
export type ClientLoader = (args: ClientLoaderArgs) => unknown;
export let defineClientLoader = <T extends ClientLoader>(
clientLoader: T
): T & { hydrate?: boolean } => clientLoader;

// clientAction
type ClientActionArgs = RRActionArgs<undefined> & {
serverAction: <T extends unstable_Action>() => Promise<unstable_Serialize<T>>;
};
export type ClientAction = (args: ClientActionArgs) => unknown;
export let defineClientAction = <T extends ClientAction>(clientAction: T): T =>
clientAction;

interface StreamTransferProps {
context: EntryContext;
identifier: number;
Expand Down
12 changes: 8 additions & 4 deletions packages/remix-server-runtime/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,18 @@
let loader1 = () => {
return { a: 1, b: new Date() };
};
let data1 = useLoaderData<typeof loader1>();
// ^? {a: number, b: Date}
function Component() {
let data1 = useLoaderData<typeof loader1>();
// ^? {a: number, b: Date}
}

let loader2 = () => {
return json({ a: 1, b: new Date() }); // this opts-out of turbo-stream
};
let data2 = useLoaderData<typeof loader2>();
// ^? JsonifyObject<{a: number, b: Date}> which is really {a: number, b: string}
function Component2() {
let data2 = useLoaderData<typeof loader2>();
// ^? JsonifyObject<{a: number, b: Date}> which is really {a: number, b: string}
}
```

You can also continue to return totally custom responses with `Response` though this continues to be outside of the typesystem since the built-in `Response` type is not generic
Expand Down
2 changes: 0 additions & 2 deletions packages/remix-server-runtime/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ export { defer, json, redirect, redirectDocument } from "./responses";
export {
SingleFetchRedirectSymbol as UNSAFE_SingleFetchRedirectSymbol,
defineLoader as unstable_defineLoader,
defineClientLoader as unstable_defineClientLoader,
defineAction as unstable_defineAction,
defineClientAction as unstable_defineClientAction,
} from "./single-fetch";
export type {
Loader as unstable_Loader,
Expand Down
19 changes: 1 addition & 18 deletions packages/remix-server-runtime/single-fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ type DataFunctionReturnValue =
// migration of loaders to return naked objects. In the next major version,
// json/defer will be removed so everything will use the new simplified typings.
// prettier-ignore
export type Serialize<T extends Loader | ClientLoader | Action | ClientAction> =
export type Serialize<T extends Loader | Action> =
Awaited<ReturnType<T>> extends TypedDeferredData<infer D> ? D :
Awaited<ReturnType<T>> extends TypedResponse<Record<string, unknown>> ? SerializeFrom<T> :
Awaited<ReturnType<T>>;
Expand Down Expand Up @@ -569,15 +569,6 @@ export type Loader = (
) => MaybePromise<DataFunctionReturnValue>;
export let defineLoader = <T extends Loader>(loader: T): T => loader;

// clientLoader
type ClientLoaderArgs = RRLoaderArgs<undefined> & {
serverLoader: <T extends Loader>() => Promise<Serialize<T>>;
};
type ClientLoader = (args: ClientLoaderArgs) => MaybePromise<Serializable>;
export let defineClientLoader = <T extends ClientLoader>(
clientLoader: T
): T & { hydrate?: boolean } => clientLoader;

// action
type ActionArgs = RRActionArgs<AppLoadContext> & {
// Context is always provided in Remix, and typed for module augmentation support.
Expand All @@ -588,11 +579,3 @@ export type Action = (
args: ActionArgs
) => MaybePromise<DataFunctionReturnValue>;
export let defineAction = <T extends Action>(action: T): T => action;

// clientAction
type ClientActionArgs = RRActionArgs<undefined> & {
serverAction: <T extends Action>() => Promise<Serialize<T>>;
};
type ClientAction = (args: ClientActionArgs) => MaybePromise<Serializable>;
export let defineClientAction = <T extends ClientAction>(clientAction: T): T =>
clientAction;

0 comments on commit 50a4cec

Please sign in to comment.