Skip to content

Commit 8a95048

Browse files
docs: improve get started guide for React to be more representative (#1214)
* docs: improve get started guide for React to be more representative * docs: revise with feedback from @phryneas * docs: minor additions --------- Co-authored-by: Leonardo Montini <lion.48m@gmail.com>
1 parent d81e8c6 commit 8a95048

File tree

1 file changed

+113
-33
lines changed

1 file changed

+113
-33
lines changed

docs/framework/react/quick-start.md

Lines changed: 113 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,54 +3,134 @@ id: quick-start
33
title: Quick Start
44
---
55

6-
The bare minimum to get started with TanStack Form is to create a form and add a field. Keep in mind that this example does not include any validation or error handling... yet.
6+
TanStack Form is unlike most form libraries you've used before. It's designed for large-scale production usage, with a focus on type safety, performance and composition for an unmatched developer experience.
7+
8+
As a result, we've developed [a philosophy around the library's usage](/form/latest/docs/philosophy) that values scalability and long-term developer experience over short and sharable code snippets.
9+
10+
Here's an example of a form following many of our best practices, which will allow you to rapidly develop even high-complexity forms after a short onboarding experience:
711

812
```tsx
913
import React from 'react'
1014
import ReactDOM from 'react-dom/client'
11-
import { useForm } from '@tanstack/react-form'
15+
import { createFormHook, createFormHookContexts } from '@tanstack/react-form'
16+
// Form components that pre-bind events from the form hook; check our "Form Composition" guide for more
17+
import { TextField, NumberField, SubmitButton } from '~our-app/ui-library'
18+
// We also support Valibot, ArkType, and any other standard schema library
19+
import { z } from 'zod'
1220

13-
export default function App() {
14-
const form = useForm({
21+
const { fieldContext, formContext } = createFormHookContexts()
22+
23+
// Allow us to bind components to the form to keep type safety but reduce production boilerplate
24+
// Define this once to have a generator of consistent form instances throughout your app
25+
const { useAppForm } = createFormHook({
26+
fieldComponents: {
27+
TextField,
28+
NumberField,
29+
},
30+
formComponents: {
31+
SubmitButton,
32+
},
33+
fieldContext,
34+
formContext,
35+
})
36+
37+
const PeoplePage = () => {
38+
const form = useAppForm({
1539
defaultValues: {
16-
fullName: '',
40+
username: '',
41+
age: 0,
42+
},
43+
validators: {
44+
// Pass a schema or function to validate
45+
onChange: z.object({
46+
username: z.string(),
47+
age: z.number().min(13),
48+
}),
1749
},
18-
onSubmit: async ({ value }) => {
50+
onSubmit: ({ value }) => {
1951
// Do something with form data
20-
console.log(value)
52+
alert(JSON.stringify(value, null, 2))
2153
},
2254
})
2355

2456
return (
25-
<div>
26-
<form
27-
onSubmit={(e) => {
28-
e.preventDefault();
29-
e.stopPropagation();
30-
form.handleSubmit();
31-
}}
32-
>
33-
<div>
34-
<form.Field
35-
name="fullName"
36-
children={(field) => (
37-
<input
38-
name={field.name}
39-
value={field.state.value}
40-
onBlur={field.handleBlur}
41-
onChange={(e) => field.handleChange(e.target.value)}
42-
/>
43-
)}
44-
/>
45-
</div>
46-
<button type="submit">Submit</button>
47-
</form>
48-
</div>
57+
<form
58+
onSubmit={(e) => {
59+
e.preventDefault()
60+
form.handleSubmit()
61+
}}
62+
>
63+
<h1>Personal Information</h1>
64+
{/* Components are bound to `form` and `field` to ensure extreme type safety */}
65+
{/* Use `form.AppField` to render a component bound to a single field */}
66+
<form.AppField
67+
name="username"
68+
children={(field) => <field.TextField label="Full Name" />}
69+
/>
70+
{/* The "name" property will throw a TypeScript error if typo'd */}
71+
<form.AppField
72+
name="age"
73+
children={(field) => <field.NumberField label="Age" />}
74+
/>
75+
{/* Components in `form.AppForm` have access to the form context */}
76+
<form.AppForm>
77+
<form.SubmitButton />
78+
</form.AppForm>
79+
</form>
4980
)
5081
}
5182

5283
const rootElement = document.getElementById('root')!
53-
ReactDOM.createRoot(rootElement).render(<App />)
84+
ReactDOM.createRoot(rootElement).render(<PeoplePage />)
85+
```
86+
87+
While we generally suggest using `createFormHook` for reduced boilerplate in the long-run, we also support one-off components and other behaviors using `useForm` and `form.Field`:
88+
89+
```tsx
90+
import React from 'react'
91+
import ReactDOM from 'react-dom/client'
92+
import { useForm } from '@tanstack/react-form'
93+
94+
const PeoplePage = () => {
95+
const form = useForm({
96+
defaultValues: {
97+
username: '',
98+
age: 0
99+
},
100+
onSubmit: ({ value }) => {
101+
// Do something with form data
102+
alert(JSON.stringify(value, null, 2));
103+
},
104+
});
105+
106+
return (
107+
<form.Field
108+
name="age"
109+
validators={{
110+
// We can choose between form-wide and field-specific validators
111+
onChange: ({ value }) =>
112+
value > 13 ? undefined : 'Must be 13 or older',
113+
}}
114+
children={(field) => (
115+
<>
116+
<input
117+
name={field.name}
118+
value={field.state.value}
119+
onBlur={field.handleBlur}
120+
type="number"
121+
onChange={(e) => field.handleChange(e.target.valueAsNumber)}
122+
/>
123+
{field.state.meta.errors.length ? (
124+
<em>{field.state.meta.errors.join(',')}</em>
125+
) : null}
126+
</>
127+
)}
128+
/>
129+
);
130+
}
131+
132+
const rootElement = document.getElementById('root')!
133+
ReactDOM.createRoot(rootElement).render(<PeoplePage />)
54134
```
55135

56-
From here, you'll be ready to explore all of the other features of TanStack Form!
136+
All properties from `useForm` can be used in `useAppForm` and all properties from `form.Field` can be used in `form.AppField`.

0 commit comments

Comments
 (0)