Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
48a9724
chore: update to start rc
Balastrong Sep 25, 2025
18eb65a
fix: build
Balastrong Sep 25, 2025
59b1990
chore: update start example
Balastrong Sep 25, 2025
c3e25ee
Merge branch 'main' into chore/update-start-rc
Balastrong Sep 25, 2025
ae5a0c9
revert tsconfig
Balastrong Sep 25, 2025
91d8de8
changeset
Balastrong Sep 25, 2025
e58f70b
Trial check deps
lachlancollins Sep 26, 2025
d0a6ff4
Fix action permission
lachlancollins Sep 26, 2025
7b96e5b
Undo changes
lachlancollins Sep 26, 2025
5c09d0a
Merge branch 'main' into chore/update-start-rc
lachlancollins Sep 26, 2025
01a7b08
fix: remove cjs from react-form to fix start build
Balastrong Sep 29, 2025
e31c68d
docs: update changeset
Balastrong Sep 29, 2025
1f2ca50
fix: remove main from package.json
Balastrong Sep 29, 2025
4ffd2af
Update lockfile
lachlancollins Sep 29, 2025
79e0a3c
chore: scafold packages
harry-whorlow Oct 3, 2025
de3a3c2
chore: reverte removal of cjs
harry-whorlow Oct 3, 2025
6ecd592
chore: remove framework adapters from react-form
harry-whorlow Oct 3, 2025
2c93b6d
chore: clean up packages
harry-whorlow Oct 3, 2025
95fcd2e
chore: fix type export
harry-whorlow Oct 3, 2025
18df298
chore: move useTransform to adapters and remove it from core
harry-whorlow Oct 8, 2025
851e9cb
Merge branch 'main' into chore/update-start-rc
harry-whorlow Oct 8, 2025
61c05ef
fix: knip
harry-whorlow Oct 8, 2025
98e2c2e
fix: sherif
harry-whorlow Oct 8, 2025
9ab4a98
fix: lockfile
harry-whorlow Oct 8, 2025
2f50f7b
chore: test useTransform
harry-whorlow Oct 8, 2025
7630874
docs: update docs and examples
harry-whorlow Oct 8, 2025
1bc6631
chore: fix package versions
harry-whorlow Oct 8, 2025
4263ce3
fix: update imports of examples
harry-whorlow Oct 8, 2025
bec8786
fix: sherif
harry-whorlow Oct 8, 2025
b647c03
fix: client directive
harry-whorlow Oct 8, 2025
8c0b6f7
fix: missed imports
harry-whorlow Oct 8, 2025
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
14 changes: 13 additions & 1 deletion .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,19 @@
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"fixed": [],
"fixed": [
[
"@tanstack/form-core",
"@tanstack/react-form",
"@tanstack/react-form-start",
"@tanstack/react-form-remix",
"@tanstack/react-form-nextjs",
"@tanstack/angular-form",
"@tanstack/vue-form",
"@tanstack/solid-form",
"@tanstack/svelt-form"
]
],
"linked": [],
"ignore": []
}
5 changes: 5 additions & 0 deletions .changeset/cruel-clubs-agree.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tanstack/react-form': minor
---

Update Start to Release Candidate version
31 changes: 15 additions & 16 deletions docs/framework/react/guides/ssr.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Let's start by creating a `formOption` that we'll use to share the form's shape

```typescript
// app/routes/index.tsx, but can be extracted to any other path
import { formOptions } from '@tanstack/react-form'
import { formOptions } from '@tanstack/react-form-start'

// You can pass other form options here
export const formOpts = formOptions({
Expand All @@ -44,7 +44,7 @@ Next, we can create [a Start Server Function](https://tanstack.com/start/latest/
import {
createServerValidate,
ServerValidateError,
} from '@tanstack/react-form/start'
} from '@tanstack/react-form-start'

const serverValidate = createServerValidate({
...formOpts,
Expand Down Expand Up @@ -93,7 +93,7 @@ Then we need to establish a way to grab the form data from `serverValidate`'s `r

```typescript
// app/routes/index.tsx, but can be extracted to any other path
import { getFormData } from '@tanstack/react-form/start'
import { getFormData } from '@tanstack/react-form-start'

export const getFormDataFromServer = createServerFn({ method: 'GET' }).handler(
async () => {
Expand All @@ -106,13 +106,13 @@ Finally, we'll use `getFormDataFromServer` in our loader to get the state from o

```tsx
// app/routes/index.tsx
import { createFileRoute } from '@tanstack/react-router'
import {
createFileRoute
mergeForm,
useForm,
useStore,
useTransform,
} from '@tanstack/react-form'
} from '@tanstack/react-form-start'

export const Route = createFileRoute('/')({
component: Home,
Expand Down Expand Up @@ -192,7 +192,7 @@ Let's start by creating a `formOption` that we'll use to share the form's shape
```typescript
// shared-code.ts
// Notice the import path is different from the client
import { formOptions } from '@tanstack/react-form/nextjs'
import { formOptions } from '@tanstack/react-form-nextjs'

// You can pass other form options here
export const formOpts = formOptions({
Expand All @@ -213,7 +213,7 @@ Next, we can create [a React Server Action](https://playfulprogramming.com/posts
import {
ServerValidateError,
createServerValidate,
} from '@tanstack/react-form/nextjs'
} from '@tanstack/react-form-nextjs'
import { formOpts } from './shared-code'

// Create the server action that will infer the types of the form from `formOpts`
Expand Down Expand Up @@ -255,14 +255,13 @@ Finally, we'll use `someAction` in our client-side form component.
'use client'

import { useActionState } from 'react'
import { initialFormState } from '@tanstack/react-form/nextjs'
// Notice the import is from `react-form`, not `react-form/nextjs`
import {
initialFormState
mergeForm,
useForm,
useStore,
useTransform,
} from '@tanstack/react-form'
} from '@tanstack/react-form-nextjs'
import someAction from './action'
import { formOpts } from './shared-code'

Expand Down Expand Up @@ -327,7 +326,7 @@ Here, we're using [React's `useActionState` hook](https://playfulprogramming.com
> x You're importing a component that needs `useState`. This React hook only works in a client component. To fix, mark the file (or its parent) with the `"use client"` directive.
> ```
>
> This is because you're not importing server-side code from `@tanstack/react-form/nextjs`. Ensure you're importing the correct module based on the environment.
> This is because you're not importing server-side code from `@tanstack/react-form-nextjs`. Ensure you're importing the correct module based on the environment.
>
> [This is a limitation of Next.js](https://github.com/phryneas/rehackt). Other meta-frameworks will likely not have this same problem.

Expand All @@ -347,7 +346,7 @@ Let's start by creating a `formOption` that we'll use to share the form's shape

```typescript
// routes/_index/route.tsx
import { formOptions } from '@tanstack/react-form/remix'
import { formOptions } from '@tanstack/react-form-remix'

// You can pass other form options here
export const formOpts = formOptions({
Expand All @@ -367,7 +366,7 @@ import {
ServerValidateError,
createServerValidate,
formOptions,
} from '@tanstack/react-form/remix'
} from '@tanstack/react-form-remix'

import type { ActionFunctionArgs } from '@remix-run/node'

Expand Down Expand Up @@ -410,10 +409,10 @@ Finally, the `action` will be called when the form submits.

```tsx
// routes/_index/route.tsx
import { Form, useActionData } from '@remix-run/react'

import {
Form,
mergeForm,
useActionData
useForm,
useStore,
useTransform,
Expand All @@ -423,7 +422,7 @@ import {
createServerValidate,
formOptions,
initialFormState,
} from '@tanstack/react-form/remix'
} from '@tanstack/react-form-remix'

import type { ActionFunctionArgs } from '@remix-run/node'

Expand Down
2 changes: 1 addition & 1 deletion examples/react/next-server-actions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"_test:types": "tsc"
},
"dependencies": {
"@tanstack/react-form": "^1.23.6",
"@tanstack/react-form-nextjs": "^1.23.6",
"@tanstack/react-store": "^0.7.7",
"next": "15.5.3",
"react": "^19.0.0",
Expand Down
2 changes: 1 addition & 1 deletion examples/react/next-server-actions/src/app/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import {
ServerValidateError,
createServerValidate,
} from '@tanstack/react-form/nextjs'
} from '@tanstack/react-form-nextjs'
import { formOpts } from './shared-code'

const serverValidate = createServerValidate({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
'use client'

import { useActionState } from 'react'
import { mergeForm, useForm, useTransform } from '@tanstack/react-form'
import { initialFormState } from '@tanstack/react-form/nextjs'
import {
initialFormState,
mergeForm,
useForm,
useTransform,
} from '@tanstack/react-form-nextjs'
import { useStore } from '@tanstack/react-store'
import someAction from './action'
import { formOpts } from './shared-code'
Expand Down
2 changes: 1 addition & 1 deletion examples/react/next-server-actions/src/app/shared-code.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { formOptions } from '@tanstack/react-form/nextjs'
import { formOptions } from '@tanstack/react-form-nextjs'

export const formOpts = formOptions({
defaultValues: {
Expand Down
7 changes: 4 additions & 3 deletions examples/react/remix/app/routes/_index/route.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { Form, useActionData } from '@remix-run/react'

import { mergeForm, useForm, useTransform } from '@tanstack/react-form'
import {
ServerValidateError,
createServerValidate,
formOptions,
initialFormState,
} from '@tanstack/react-form/remix'
mergeForm,
useForm,
useTransform,
} from '@tanstack/react-form-remix'
import { useStore } from '@tanstack/react-store'

import type { ActionFunctionArgs } from '@remix-run/node'
Expand Down
2 changes: 1 addition & 1 deletion examples/react/remix/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"@remix-run/node": "^2.17.1",
"@remix-run/react": "^2.17.1",
"@remix-run/serve": "^2.17.1",
"@tanstack/react-form": "^1.23.6",
"@tanstack/react-form-remix": "^1.23.6",
"@tanstack/react-store": "^0.7.7",
"isbot": "^5.1.30",
"react": "^19.0.0",
Expand Down
6 changes: 3 additions & 3 deletions examples/react/tanstack-start/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
},
"dependencies": {
"@tanstack/react-devtools": "^0.7.0",
"@tanstack/react-form": "^1.23.6",
"@tanstack/react-form-devtools": "^0.1.6",
"@tanstack/react-router": "^1.131.50",
"@tanstack/react-start": "^1.131.50",
"@tanstack/react-form-start": "^1.23.6",
"@tanstack/react-router": "^1.132.6",
"@tanstack/react-start": "^1.132.32",
"@tanstack/react-store": "^0.7.7",
"react": "^19.0.0",
"react-dom": "^19.0.0"
Expand Down
8 changes: 8 additions & 0 deletions examples/react/tanstack-start/src/routeTree.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,11 @@ const rootRouteChildren: RootRouteChildren = {
export const routeTree = rootRouteImport
._addFileChildren(rootRouteChildren)
._addFileTypes<FileRouteTypes>()

import type { getRouter } from './router.tsx'
import type { createStart } from '@tanstack/react-start'
declare module '@tanstack/react-start' {
interface Register {
router: Awaited<ReturnType<typeof getRouter>>
}
}
4 changes: 2 additions & 2 deletions examples/react/tanstack-start/src/router.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createRouter as createTanStackRouter } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen'

export function createRouter() {
export function getRouter() {
const router = createTanStackRouter({
routeTree,
defaultPreload: 'intent',
Expand All @@ -13,6 +13,6 @@ export function createRouter() {

declare module '@tanstack/react-router' {
interface Register {
router: ReturnType<typeof createRouter>
router: ReturnType<typeof getRouter>
}
}
2 changes: 1 addition & 1 deletion examples/react/tanstack-start/src/routes/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createFileRoute } from '@tanstack/react-router'
import { mergeForm, useForm, useTransform } from '@tanstack/react-form'
import { mergeForm, useForm, useTransform } from '@tanstack/react-form-start'
import { useStore } from '@tanstack/react-store'
import { getFormDataFromServer, handleForm } from 'src/utils/form'
import { formOpts } from 'src/utils/form-isomorphic'
Expand Down
9 changes: 3 additions & 6 deletions examples/react/tanstack-start/src/utils/form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
ServerValidateError,
createServerValidate,
getFormData,
} from '@tanstack/react-form/start'
} from '@tanstack/react-form-start'
import { setResponseStatus } from '@tanstack/react-start/server'
import { formOpts } from './form-isomorphic'

Expand All @@ -16,11 +16,8 @@ const serverValidate = createServerValidate({
},
})

export const handleForm = createServerFn({
method: 'POST',
response: 'raw',
})
.validator((data: unknown) => {
export const handleForm = createServerFn({ method: 'POST' })
.inputValidator((data: unknown) => {
if (!(data instanceof FormData)) {
throw new Error('Invalid form data')
}
Expand Down
Empty file.
35 changes: 35 additions & 0 deletions packages/react-form-nextjs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<img src="https://static.scarf.sh/a.png?x-pxid=be2d8a11-9712-4c1d-9963-580b2d4fb133" />

![TanStack Form Header](https://github.com/TanStack/form/raw/main/media/repo-header.png)

Hooks for managing form state in React

<a href="https://twitter.com/intent/tweet?button_hashtag=TanStack" target="\_parent">
<img alt="#TanStack" src="https://img.shields.io/twitter/url?color=%2308a0e9&label=%23TanStack&style=social&url=https%3A%2F%2Ftwitter.com%2Fintent%2Ftweet%3Fbutton_hashtag%3DTanStack">
</a><a href="https://discord.com/invite/WrRKjPJ" target="\_parent">
<img alt="" src="https://img.shields.io/badge/Discord-TanStack-%235865F2" />
</a><a href="https://github.com/TanStack/form/actions?query=workflow%3A%22react-form+tests%22">
<img src="https://github.com/TanStack/form/workflows/react-form%20tests/badge.svg" />
</a><a href="https://www.npmjs.com/package/@tanstack/form-core" target="\_parent">
<img alt="" src="https://img.shields.io/npm/dm/@tanstack/form-core.svg" />
</a><a href="https://bundlephobia.com/package/@tanstack/react-form@latest" target="\_parent">
<img alt="" src="https://badgen.net/bundlephobia/minzip/@tanstack/react-form" />
</a><a href="#badge">
<img alt="semantic-release" src="https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg">
</a><a href="https://github.com/TanStack/form/discussions">
<img alt="Join the discussion on Github" src="https://img.shields.io/badge/Github%20Discussions%20%26%20Support-Chat%20now!-blue" />
</a><a href="https://bestofjs.org/projects/tanstack-form"><img alt="Best of JS" src="https://img.shields.io/endpoint?url=https://bestofjs-serverless.now.sh/api/project-badge?fullName=TanStack%form%26since=daily" /></a><a href="https://github.com/TanStack/form/" target="\_parent">
<img alt="" src="https://img.shields.io/github/stars/TanStack/form.svg?style=social&label=Star" />
</a><a href="https://twitter.com/tannerlinsley" target="\_parent">
<img alt="" src="https://img.shields.io/twitter/follow/tannerlinsley.svg?style=social&label=Follow" />
</a> <a href="https://gitpod.io/from-referrer/">
<img src="https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod" alt="Gitpod Ready-to-Code"/>
</a>

Enjoy this library? Try the entire [TanStack](https://tanstack.com)! [TanStack Table](https://github.com/TanStack/table), [TanStack Router](https://github.com/tanstack/router), [TanStack Virtual](https://github.com/tanstack/virtual), [React Charts](https://github.com/TanStack/react-charts), [React Ranger](https://github.com/TanStack/ranger)

## Visit [tanstack.com/form](https://tanstack.com/form) for docs, guides, API and more!

### [Become a Sponsor!](https://github.com/sponsors/tannerlinsley/)

<!-- Use the force, Luke -->
25 changes: 25 additions & 0 deletions packages/react-form-nextjs/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// @ts-check

import pluginReact from '@eslint-react/eslint-plugin'
import reactCompiler from 'eslint-plugin-react-compiler'
import pluginReactHooks from 'eslint-plugin-react-hooks'
import rootConfig from '../../eslint.config.js'

export default [
...rootConfig,
{
files: ['**/*.{ts,tsx}'],
...pluginReact.configs.recommended,
},
{
plugins: {
'react-hooks': pluginReactHooks,
'react-compiler': reactCompiler,
},
rules: {
'react-hooks/exhaustive-deps': 'error',
'react-hooks/rules-of-hooks': 'error',
'react-compiler/react-compiler': 'error',
},
},
]
Loading
Loading