Skip to content

Commit

Permalink
feat: force createServerFn usage with getFormData (#826)
Browse files Browse the repository at this point in the history
  • Loading branch information
crutchcorn authored Jul 8, 2024
1 parent 04fda1c commit 3b91e6c
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 10 deletions.
17 changes: 13 additions & 4 deletions docs/framework/react/guides/ssr.md
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
}),
})

Expand Down
5 changes: 2 additions & 3 deletions examples/react/tanstack-start/app/routes/index.tsx
Original file line number Diff line number Diff line change
@@ -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(),
}),
})

Expand Down
5 changes: 5 additions & 0 deletions examples/react/tanstack-start/app/utils/form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { formOptions } from '@tanstack/react-form'
import {
ServerValidateError,
createServerValidate,
getFormData,
} from '@tanstack/react-form/start'

export const formOpts = formOptions({
Expand Down Expand Up @@ -43,3 +44,7 @@ export const handleForm = createServerFn(
})
},
)

export const getFormDataFromServer = createServerFn('GET', async (_, ctx) => {
return getFormData(ctx)
})
8 changes: 5 additions & 3 deletions packages/react-form/src/start/getFormData.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import { createServerFn } from '@tanstack/start'
import { type FetchFn } from '@tanstack/start'
import { _tanstackInternalsCookie } from './utils'
import type { ServerFormState } from './types'

type FetchFnCtx = Parameters<FetchFn<never, never>>[1]

export const initialFormState = {
errorMap: {
onServer: undefined,
},
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<any>
// Delete the cookie before it hits the client again¸
ctx.request.headers.delete('Cookie')
if (!data) return initialFormState
return data
})
}

0 comments on commit 3b91e6c

Please sign in to comment.