0
# Form Component
1
2
Core form wrapper component that provides form context, state management, and submission handling with efficient subscription-based updates.
3
4
## Capabilities
5
6
### Form Component
7
8
The main Form component that wraps form elements and provides form state management through React context.
9
10
```typescript { .api }
11
/**
12
* Main form wrapper component providing form context and state management
13
* @param props - Form configuration and render props
14
* @returns React element with form context
15
*/
16
const Form: <FormValues = Record<string, any>>(
17
props: FormProps<FormValues>
18
) => React.ReactElement;
19
20
interface FormProps<FormValues = Record<string, any>>
21
extends Config<FormValues>,
22
RenderableProps<FormRenderProps<FormValues>> {
23
/** Form state subscription configuration */
24
subscription?: FormSubscription;
25
/** Form decorators for additional functionality */
26
decorators?: Decorator<FormValues>[];
27
/** External form API instance */
28
form?: FormApi<FormValues>;
29
/** Custom equality function for initial values comparison */
30
initialValuesEqual?: (
31
a?: Record<string, any>,
32
b?: Record<string, any>
33
) => boolean;
34
}
35
36
interface FormRenderProps<FormValues = Record<string, any>>
37
extends FormState<FormValues> {
38
/** Form submission handler with event handling */
39
handleSubmit: (
40
event?: SubmitEvent
41
) => Promise<Record<string, any> | undefined> | undefined;
42
/** Form API instance for programmatic control */
43
form: FormApi<FormValues>;
44
}
45
```
46
47
**Usage Examples:**
48
49
```typescript
50
import React from "react";
51
import { Form } from "react-final-form";
52
53
// Basic form with render prop
54
function BasicForm() {
55
return (
56
<Form
57
onSubmit={(values) => console.log(values)}
58
render={({ handleSubmit, pristine, invalid }) => (
59
<form onSubmit={handleSubmit}>
60
{/* form fields */}
61
<button type="submit" disabled={pristine || invalid}>
62
Submit
63
</button>
64
</form>
65
)}
66
/>
67
);
68
}
69
70
// Form with initial values and validation
71
function ValidatedForm() {
72
const validate = (values: any) => {
73
const errors: any = {};
74
if (!values.firstName) {
75
errors.firstName = "Required";
76
}
77
return errors;
78
};
79
80
return (
81
<Form
82
onSubmit={(values) => console.log(values)}
83
initialValues={{ firstName: "John" }}
84
validate={validate}
85
render={({ handleSubmit, form, submitting, values }) => (
86
<form onSubmit={handleSubmit}>
87
{/* form fields */}
88
<button type="submit" disabled={submitting}>
89
Submit
90
</button>
91
<button type="button" onClick={form.reset}>
92
Reset
93
</button>
94
<pre>{JSON.stringify(values, null, 2)}</pre>
95
</form>
96
)}
97
/>
98
);
99
}
100
101
// Form with children function
102
function ChildrenForm() {
103
return (
104
<Form onSubmit={(values) => console.log(values)}>
105
{({ handleSubmit, submitting }) => (
106
<form onSubmit={handleSubmit}>
107
{/* form fields */}
108
<button type="submit" disabled={submitting}>
109
Submit
110
</button>
111
</form>
112
)}
113
</Form>
114
);
115
}
116
```
117
118
### Form Subscription Configuration
119
120
The Form component supports customizable subscriptions to optimize rendering performance by only updating when specific form state changes occur.
121
122
```typescript { .api }
123
interface FormSubscription {
124
active?: boolean;
125
dirty?: boolean;
126
dirtyFields?: boolean;
127
dirtySinceLastSubmit?: boolean;
128
error?: boolean;
129
errors?: boolean;
130
hasSubmitErrors?: boolean;
131
hasValidationErrors?: boolean;
132
initialValues?: boolean;
133
invalid?: boolean;
134
modified?: boolean;
135
modifiedSinceLastSubmit?: boolean;
136
pristine?: boolean;
137
submitError?: boolean;
138
submitErrors?: boolean;
139
submitFailed?: boolean;
140
submitSucceeded?: boolean;
141
submitting?: boolean;
142
touched?: boolean;
143
valid?: boolean;
144
validating?: boolean;
145
values?: boolean;
146
visited?: boolean;
147
}
148
```
149
150
**Usage Example:**
151
152
```typescript
153
import { Form } from "react-final-form";
154
155
function OptimizedForm() {
156
return (
157
<Form
158
onSubmit={(values) => console.log(values)}
159
subscription={{ submitting: true, pristine: true, invalid: true }}
160
render={({ handleSubmit, submitting, pristine, invalid }) => (
161
<form onSubmit={handleSubmit}>
162
{/* Only re-renders when submitting, pristine, or invalid changes */}
163
<button type="submit" disabled={submitting || pristine || invalid}>
164
Submit
165
</button>
166
</form>
167
)}
168
/>
169
);
170
}
171
```
172
173
### Form Configuration Options
174
175
The Form component accepts all configuration options from the underlying Final Form library through the Config interface.
176
177
```typescript { .api }
178
interface Config<FormValues = Record<string, any>> {
179
/** Debug mode for development */
180
debug?: (state: FormState<FormValues>, action: string) => void;
181
/** Whether to destroy field state when field is unregistered */
182
destroyOnUnregister?: boolean;
183
/** Initial form values */
184
initialValues?: Partial<FormValues>;
185
/** Whether to keep dirty values when reinitializing */
186
keepDirtyOnReinitialize?: boolean;
187
/** Custom mutators for form state manipulation */
188
mutators?: Record<string, Mutator<FormValues>>;
189
/** Form submission handler */
190
onSubmit: (
191
values: FormValues,
192
form: FormApi<FormValues>,
193
callback?: (errors?: SubmissionErrors) => void
194
) => SubmissionErrors | Promise<SubmissionErrors> | undefined | void;
195
/** Form-level validation function */
196
validate?: (values: FormValues) => ValidationErrors | Promise<ValidationErrors>;
197
/** Values to validate on each change */
198
validateOnBlur?: boolean;
199
}
200
```
201
202
### Error Handling
203
204
Forms provide comprehensive error handling through multiple error sources and clear error state management.
205
206
```typescript { .api }
207
interface FormState<FormValues = Record<string, any>> {
208
/** Current form validation errors */
209
errors?: ValidationErrors;
210
/** Submission errors from the last submit attempt */
211
submitErrors?: SubmissionErrors;
212
/** General submission error */
213
submitError?: any;
214
/** Whether the last submission failed */
215
submitFailed?: boolean;
216
/** Whether the last submission succeeded */
217
submitSucceeded?: boolean;
218
/** Whether form has validation errors */
219
hasValidationErrors?: boolean;
220
/** Whether form has submission errors */
221
hasSubmitErrors?: boolean;
222
}
223
224
type ValidationErrors = Record<string, any>;
225
type SubmissionErrors = Record<string, any>;
226
```
227
228
**Usage Example:**
229
230
```typescript
231
function ErrorHandlingForm() {
232
const onSubmit = async (values: any) => {
233
// Simulate server validation
234
if (values.email === "taken@example.com") {
235
return { email: "Email already taken" };
236
}
237
// Success case
238
console.log("Submitted:", values);
239
};
240
241
return (
242
<Form
243
onSubmit={onSubmit}
244
render={({ handleSubmit, submitError, hasSubmitErrors, errors }) => (
245
<form onSubmit={handleSubmit}>
246
{submitError && <div className="error">{submitError}</div>}
247
{hasSubmitErrors && (
248
<div className="error">Please fix the errors below</div>
249
)}
250
{/* form fields */}
251
</form>
252
)}
253
/>
254
);
255
}
256
```