Skip to content

tRPC v12 isn’t on npm yet. The @trpc12/* packages on this site can’t be installed until it’s released. Use v11 today

tRPC

Hydration and offline mutations

hydrationOptions() sends the cache to the browser with the client's serializer, and persisted mutations resume with setMutationDefaults.

On this page

Hydration

hydrationOptions({ client }) returns { dehydrate, hydrate } options that serialize data with the client's serializer, so the types it keeps (with danSON: Date, Map, Set, bigint, custom types) survive the trip, and that dehydrate pending queries. Their data is serialized once it settles. Without client it uses plain JSON; serializer overrides both.

new new QueryClient(config?: QueryClientConfig): QueryClientQueryClient({ QueryClientConfig.defaultOptions?: DefaultOptions<Error> | undefineddefaultOptions: 
function hydrationOptions(opts?: HydrationOptionsOptions): {
    dehydrate: DehydrateOptions;
    hydrate: NonNullable<HydrateOptions["defaultOptions"]>;
}
hydrationOptions
({ HydrationOptionsOptions.client?: object | undefinedclient }) });

Use the same options for the server's QueryClient and the browser's. In React Server Components, createTrpcRsc dehydrates with them on the server, and the browser's QueryClient takes them as above (React Server Components).

Offline mutations

A paused mutation that was persisted (with persistQueryClient, say) can only resume if the restored client knows its mutationFn. mutationOptions() returns the key and the function, so register them as defaults:

const 
const createPost: MutationOptionsOut<{
    title: string;
}, {
    id: string;
    title: string;
    author: string | null;
    createdAt: string;
}, NonNullable<UnexpectedError | (TrpcError<"UNAUTHORIZED", undefined> & {
    readonly defined: true;
}) | (TrpcError<"BAD_REQUEST", InputValidationErrorData<{
    readonly code: "invalid_type";
    readonly expected: $ZodInvalidTypeExpected;
    readonly path: readonly [] | readonly ["title"];
    readonly message: string;
} | {
    readonly code: "too_big";
    readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
    ... 4 more ...;
    readonly message: string;
} | ... 9 more ... | {
    ...;
}>> & {
    ...;
})>, unknown>
createPost
=
const trpc: TrpcQueryUtils<TrpcClient<{
    post: {
        byId: BuildProcedure<InputDef<RootDef<Context, {}>, ZodObject<{
            id: ZodString;
        }, $strip>>, "query", {
            output: Post;
            errors: TrpcError<"NOT_FOUND", {
                id: string;
            }>;
            services: never;
            unmapped: never;
        }>;
        list: BuildProcedure<RootDef<Context, {}>, "query", {
            output: Post[];
            errors: never;
            services: never;
            unmapped: never;
        }>;
        create: BuildProcedure<InputDef<With<RootDef<Context, {}>, {
            ctx: Context;
            ctxAdded: {
                ...;
            };
            inputOut: Unset;
            errors: TrpcError<...>;
            shorts: never;
        }>, ZodObject<...>>, "mutation", {
            ...;
        }>;
    };
}, {}, undefined, LinksTypes<...>>>
trpc
.
post: TrpcQueryUtils<ClientRouter<{
    byId: BuildProcedure<InputDef<RootDef<Context, {}>, ZodObject<{
        id: ZodString;
    }, $strip>>, "query", {
        output: Post;
        errors: TrpcError<"NOT_FOUND", {
            id: string;
        }>;
        services: never;
        unmapped: never;
    }>;
    list: BuildProcedure<RootDef<Context, {}>, "query", {
        output: Post[];
        errors: never;
        services: never;
        unmapped: never;
    }>;
    create: BuildProcedure<InputDef<With<RootDef<Context, {}>, {
        ctx: Context;
        ctxAdded: {
            ...;
        };
        inputOut: Unset;
        errors: TrpcError<...>;
        shorts: never;
    }>, ZodObject<...>>, "mutation", {
        ...;
    }>;
}, {}, undefined, LinksTypes<...>>>
post
.
create: MutationProcedureUtils<{
    title: string;
}, {
    id: string;
    title: string;
    author: string | null;
    createdAt: string;
}, NonNullable<UnexpectedError | (TrpcError<"UNAUTHORIZED", undefined> & {
    readonly defined: true;
}) | (TrpcError<"BAD_REQUEST", InputValidationErrorData<{
    readonly code: "invalid_type";
    readonly expected: $ZodInvalidTypeExpected;
    readonly path: readonly [] | readonly ["title"];
    readonly message: string;
} | {
    readonly code: "too_big";
    readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
    ... 4 more ...;
    readonly message: string;
} | ... 9 more ... | {
    ...;
}>> & {
    ...;
})>, Omit<...>>
create
.
MutationProcedureUtils<{ title: string; }, { id: string; title: string; author: string | null; createdAt: string; }, NonNullable<UnexpectedError | (TrpcError<"UNAUTHORIZED", undefined> & { ...; }) | (TrpcError<...> & { ...; })>, Omit<...>>.mutationOptions<unknown>(opts?: (ContextBag<Omit<NonNullable<{
    signal?: AbortSignal | undefined;
} & BuiltinCallOptions & {}>, "signal" | "lastEventId">> & MutationOptionsIn<{
    title: string;
}, {
    id: string;
    title: string;
    author: string | null;
    createdAt: string;
}, NonNullable<UnexpectedError | (TrpcError<"UNAUTHORIZED", undefined> & {
    readonly defined: true;
}) | (TrpcError<"BAD_REQUEST", InputValidationErrorData<{
    readonly code: "invalid_type";
    readonly expected: $ZodInvalidTypeExpected;
    readonly path: readonly [] | readonly [...];
    readonly message: string;
} | ... 10 more ... | {
    ...;
}>> & {
    ...;
})>, unknown>) | undefined): MutationOptionsOut<...>
mutationOptions
();
const queryClient: QueryClientqueryClient.
QueryClient.setMutationDefaults<{
    id: string;
    title: string;
    author: string | null;
    createdAt: string;
}, (TrpcError<"UNAUTHORIZED", undefined> & {
    readonly defined: true;
}) | (TrpcError<"BAD_REQUEST", InputValidationErrorData<{
    readonly code: "invalid_type";
    readonly expected: $ZodInvalidTypeExpected;
    readonly path: readonly [] | readonly ["title"];
    readonly message: string;
} | {
    readonly code: "too_big";
    readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
    readonly maximum: string | number;
    readonly inclusive?: boolean | undefined;
    readonly exact?: boolean | undefined;
    readonly path: readonly [] | readonly [...];
    readonly message: string;
} | ... 9 more ... | {
    ...;
}>> & {
    ...;
}) | (TrpcError<...> & {
    ...;
}), {
    ...;
}, unknown>(mutationKey: MutationKey, options: OmitKeyof<...>): void
setMutationDefaults
(
const createPost: MutationOptionsOut<{
    title: string;
}, {
    id: string;
    title: string;
    author: string | null;
    createdAt: string;
}, NonNullable<UnexpectedError | (TrpcError<"UNAUTHORIZED", undefined> & {
    readonly defined: true;
}) | (TrpcError<"BAD_REQUEST", InputValidationErrorData<{
    readonly code: "invalid_type";
    readonly expected: $ZodInvalidTypeExpected;
    readonly path: readonly [] | readonly ["title"];
    readonly message: string;
} | {
    readonly code: "too_big";
    readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
    ... 4 more ...;
    readonly message: string;
} | ... 9 more ... | {
    ...;
}>> & {
    ...;
})>, unknown>
createPost
.mutationKey: TrpcMutationKeymutationKey,
const createPost: MutationOptionsOut<{
    title: string;
}, {
    id: string;
    title: string;
    author: string | null;
    createdAt: string;
}, NonNullable<UnexpectedError | (TrpcError<"UNAUTHORIZED", undefined> & {
    readonly defined: true;
}) | (TrpcError<"BAD_REQUEST", InputValidationErrorData<{
    readonly code: "invalid_type";
    readonly expected: $ZodInvalidTypeExpected;
    readonly path: readonly [] | readonly ["title"];
    readonly message: string;
} | {
    readonly code: "too_big";
    readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
    ... 4 more ...;
    readonly message: string;
} | ... 9 more ... | {
    ...;
}>> & {
    ...;
})>, unknown>
createPost
);
// after restoring: await queryClient.resumePausedMutations();