From 3b91e6c7fc8b9815c058524932b728b6936d3dc5 Mon Sep 17 00:00:00 2001 From: Corbin Crutchley Date: Mon, 8 Jul 2024 13:05:24 -0700 Subject: [PATCH] feat: force createServerFn usage with getFormData (#826) --- docs/framework/react/guides/ssr.md | 17 +++++++++++++---- .../react/tanstack-start/app/routes/index.tsx | 5 ++--- .../react/tanstack-start/app/utils/form.tsx | 5 +++++ packages/react-form/src/start/getFormData.tsx | 8 +++++--- 4 files changed, 25 insertions(+), 10 deletions(-) diff --git a/docs/framework/react/guides/ssr.md b/docs/framework/react/guides/ssr.md index 0ff3a8e96..76a54cadb 100644 --- a/docs/framework/react/guides/ssr.md +++ b/docs/framework/react/guides/ssr.md @@ -82,19 +82,28 @@ export const handleForm = createServerFn( ) ``` -Finally, we'll use `getFormData` in our loader to get the state from our server into our client and `handleForm` in our client-side form component. +Then we need to establish a way to grab the form data from `serverValidate`'s `response` using another server action: + +```typescript +// app/routes/index.tsx, but can be extracted to any other path +import { getFormData } from '@tanstack/react-form/start' + +export const getFormDataFromServer = createServerFn('GET', async (_, ctx) => { + return getFormData(ctx) +}) +``` + +Finally, we'll use `getFormDataFromServer` in our loader to get the state from our server into our client and `handleForm` in our client-side form component. ```tsx // app/routes/index.tsx import { createFileRoute } from '@tanstack/react-router' import { mergeForm, useForm, useTransform } from '@tanstack/react-form' -import { getFormData } from '@tanstack/react-form/start' -import { formOpts, handleForm } from '~/utils/form' export const Route = createFileRoute('/')({ component: Home, loader: async () => ({ - state: await getFormData(), + state: await getFormDataFromServer(), }), }) diff --git a/examples/react/tanstack-start/app/routes/index.tsx b/examples/react/tanstack-start/app/routes/index.tsx index 21e8adce6..9cd4329cf 100644 --- a/examples/react/tanstack-start/app/routes/index.tsx +++ b/examples/react/tanstack-start/app/routes/index.tsx @@ -1,12 +1,11 @@ import { createFileRoute } from '@tanstack/react-router' import { mergeForm, useForm, useTransform } from '@tanstack/react-form' -import { getFormData } from '@tanstack/react-form/start' -import { formOpts, handleForm } from '~/utils/form' +import { formOpts, getFormDataFromServer, handleForm } from '~/utils/form' export const Route = createFileRoute('/')({ component: Home, loader: async () => ({ - state: await getFormData(), + state: await getFormDataFromServer(), }), }) diff --git a/examples/react/tanstack-start/app/utils/form.tsx b/examples/react/tanstack-start/app/utils/form.tsx index 85b6ebf00..407eb9a91 100644 --- a/examples/react/tanstack-start/app/utils/form.tsx +++ b/examples/react/tanstack-start/app/utils/form.tsx @@ -3,6 +3,7 @@ import { formOptions } from '@tanstack/react-form' import { ServerValidateError, createServerValidate, + getFormData, } from '@tanstack/react-form/start' export const formOpts = formOptions({ @@ -43,3 +44,7 @@ export const handleForm = createServerFn( }) }, ) + +export const getFormDataFromServer = createServerFn('GET', async (_, ctx) => { + return getFormData(ctx) +}) diff --git a/packages/react-form/src/start/getFormData.tsx b/packages/react-form/src/start/getFormData.tsx index 529487adb..642925403 100644 --- a/packages/react-form/src/start/getFormData.tsx +++ b/packages/react-form/src/start/getFormData.tsx @@ -1,7 +1,9 @@ -import { createServerFn } from '@tanstack/start' +import { type FetchFn } from '@tanstack/start' import { _tanstackInternalsCookie } from './utils' import type { ServerFormState } from './types' +type FetchFnCtx = Parameters>[1] + export const initialFormState = { errorMap: { onServer: undefined, @@ -9,7 +11,7 @@ export const initialFormState = { errors: [], } -export const getFormData = createServerFn('GET', async (_, ctx) => { +export const getFormData = async (ctx: FetchFnCtx) => { const data = (await _tanstackInternalsCookie.parse( ctx.request.headers.get('Cookie'), )) as undefined | ServerFormState @@ -17,4 +19,4 @@ export const getFormData = createServerFn('GET', async (_, ctx) => { ctx.request.headers.delete('Cookie') if (!data) return initialFormState return data -}) +}