Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: force createServerFn usage with getFormData #826

Merged
merged 1 commit into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
})
}
Loading