react-final-form-kt
v1.0.0
Published
π High performance subscription-based form state management for React
Downloads
3
Readme
π React Final Form
β Zero dependencies
β Only peer dependencies: React and π Final Form
β Opt-in subscriptions - only update on the state you need!
β π₯ 3.0k gzipped π₯
π¬ Give Feedback on React Final Form π¬
In the interest of making π React Final Form the best library it can be, we'd love your thoughts and feedback.
Installation
npm install --save react-final-form final-form
or
yarn add react-final-form final-form
Getting Started
π React Final Form is a thin React wrapper for π Final Form, which is a subscriptions-based form state management library that uses the Observer pattern, so only the components that need updating are re-rendered as the form's state changes. By default, π React Final Form subscribes to all changes, but if you want to fine tune your form to optimized blazing-fast perfection, you may specify only the form state that you care about for rendering your gorgeous UI.
You can think of it a little like GraphQL's feature of only fetching the data your component needs to render, and nothing else.
Here's what it looks like in your code:
import { Form, Field } from 'react-final-form'
const MyForm = () => (
<Form
onSubmit={onSubmit}
validate={validate}
render={({ handleSubmit, pristine, invalid }) => (
<form onSubmit={handleSubmit}>
<h2>Simple Default Input</h2>
<div>
<label>First Name</label>
<Field name="firstName" component="input" placeholder="First Name" />
</div>
<h2>An Arbitrary Reusable Input Component</h2>
<div>
<label>Interests</label>
<Field name="interests" component={InterestPicker} />
</div>
<h2>Render Function</h2>
<Field
name="bio"
render={({ input, meta }) => (
<div>
<label>Bio</label>
<textarea {...input} />
{meta.touched && meta.error && <span>{meta.error}</span>}
</div>
)}
/>
<h2>Render Function as Children</h2>
<Field name="phone">
{({ input, meta }) => (
<div>
<label>Phone</label>
<input type="text" {...input} placeholder="Phone" />
{meta.touched && meta.error && <span>{meta.error}</span>}
</div>
)}
</Field>
<button type="submit" disabled={pristine || invalid}>
Submit
</button>
</form>
)}
/>
)
Table of Contents
- Videos
- Helper Libraries
- Examples
- Simple Example
- Synchronous Record-Level Validation
- Synchronous Field-Level Validation
- Synchronous Record-Level Validation (with delayed error render)
- Asynchronous Field-Level Validation
- Hybrid Synchronous/Asynchronous Record-Level Validation
- Submission Errors
- Third Party Components
- Material-UI 3.0
- π₯ Performance Optimization Through Subscriptions π₯
- Independent Error Component
- Loading and Initializing Values
- Field Arrays
- Fields Component
- Calculated Fields
- Field Warnings
- Reusable Field Groups
- External Submit
- Wizard Form
- Parse and Format (and Normalize)
- Auto-Save with Debounce
- Auto-Save with Selective Debounce
- Auto-Save on Field Blur
- Custom Validation Engine
- Loading, Normalizing, Saving, and Reinitializing
- ποΈ Downshift Type-Ahead
- Redux Example
- Conditional Fields
- Listening for External Changes
- Focus On First Error
- Credit Card Example
- Async Redux Submission
- Declarative Form Rules
- Format String By Pattern
- AsyncTypeahead and Redux
- Format On Blur
- Styling with π Smooth-UI
- Rendering
- API
- Types
FieldProps
allowNull?: boolean
children?: ((props: FieldRenderProps) => React.Node) | React.Node
component?: React.ComponentType<FieldRenderProps> | string
defaultValue?: any
format?: ((value: any, name: string) => any) | null
formatOnBlur?: boolean
initialValue?: any
isEqual?: (a: any, b: any) => boolean
name: string
parse?: ((value: any, name: string) => any) | null
render?: (props: FieldRenderProps) => React.Node
subscription?: FieldSubscription
validate?: (value: ?any, allValues: Object, meta: ?FieldState) => ?any
validateFields?: string[]
value?: any
FieldRenderProps
input.name: string
input.onBlur: (?SyntheticFocusEvent<*>) => void
input.onChange: (SyntheticInputEvent<*> | any) => void
input.onFocus: (?SyntheticFocusEvent<*>) => void
input.value: any
meta.active?: boolean
meta.data?: Object
meta.dirty?: boolean
meta.error?: any
meta.initial?: any
meta.invalid?: boolean
meta.modified?: boolean
meta.pristine?: boolean
meta.submitError?: any
meta.submitFailed?: boolean
meta.submitSucceeded?: boolean
meta.submitting?: boolean
meta.touched?: boolean
meta.valid?: boolean
meta.visited?: boolean
FormProps
children?: ((props: FormRenderProps) => React.Node) | React.Node
component?: React.ComponentType<FormRenderProps>
debug?: DebugFunction
decorators?: Decorator[]
initialValues?: Object
initialValuesEqual?: (?Object, ?Object) => boolean
keepDirtyOnReinitialize?: boolean
mutators?: { [string]: Mutator }
onSubmit: (values: Object, form: FormApi, callback: ?(errors: ?Object) => void) => ?Object | Promise<?Object> | void
render?: (props: FormRenderProps) => React.Node
subscription?: FormSubscription
validate?: (values: Object) => Object | Promise<Object>
validateOnBlur?: boolean
FormRenderProps
batch: (fn: () => void) => void)
blur: (name: string) => void
change: (name: string, value: any) => void
focus: (name: string) => void
form: FormApi
handleSubmit: (?SyntheticEvent<HTMLFormElement>) => void
initialize: (values: Object) => void
mutators?: { [string]: Function }
reset: (newInitialValues?: Object) => void
FormSpyProps
FormSpyRenderProps
- Contributors
- Backers
- Sponsors
Videos
| | | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | | π Final Form: Form state management via Observers - HolyJS 2018, Moscow, Russia | | | | Next Generation Forms with π React Final Form β React Alicante 2018, Alicante, Spain |
Helper Libraries
Define Form and React Define Form
Define Form offers alternative typescript bindings for π Final Form. The key difference is that the form data is now a strongly typed object, rather than an any
. This makes the initialValues
config option required.
π React Final Form HTML5 Validation
A swap-in replacement for π React Final Form's <Field>
component to provide HTML5 Validation.
Final Form Material UI
A set of adaptor components to facilitate using Material-UI with π React Final Form.
Examples
Simple Example
Uses the built-in React inputs: input
, select
, and textarea
to build a
form with no validation.
Synchronous Record-Level Validation
Introduces a whole-record validation function and demonstrates how to display errors next to fields using child render functions.
Synchronous Field-Level Validation
Introduces field-level validation functions and demonstrates how to display errors next to fields using child render functions.
Synchronous Record-Level Validation (with delayed error render)
Sometimes you want to give your user a chance to make it through a brief invalid value on their way to a valid one, e.g. a date string that needs two numbers on either side of a slash. With a simple delayed rendering component, this becomes easy. Plus, the error will disappear immediately when the user fixes the problem.
Asynchronous Field-Level Validation
Demonstrates how field-level validation rules may be asynchronous (return a
Promise
), as well as how to show a "validating" spinner during the lifetime of
the Promise
.
Hybrid Synchronous/Asynchronous Record-Level Validation
Demonstrates how you can mix synchronous and asynchronous validation patterns at
the record-level, by returning errors synchronously, and falling back to an
asynchronous call (by returning a Promise
) if sync validation is passing.
Submission Errors
Demonstrates how to return submission errors from failed submits. Notice that
the Promise
should resolve to the submission error (not reject). Rejection
is reserved for communications or server exceptions.
Third Party Components
Demonstrates how easy it is to use third party input components. All the third
party component really needs is value
and onChange
, but more complex
components can accept things like errors.
Material-UI 3.0
Demonstrates how to use Material-UI 3.0 input components.
π₯ Performance Optimization Through Subscriptions π₯
Demonstrates how, by restricting which parts of form state the form component
needs to render, it reduces the number of times the whole form has to rerender.
Yet, if some part of form state is needed inside of it, the
FormSpy
component can be used to
attain it.
Independent Error Component
Demonstrates how to make an independent Error component to subscribe to and display the error for any form field.
Loading and Initializing Values
Demonstrates how a form can be initialized, after fetching data, by passing in
initialValues
as a prop.
Field Arrays
Demostrates how to use the <FieldArray/>
component, from
react-final-form-arrays
,
to render an array of inputs, as well as use push
, pop
, and remove
mutations.
Fields Component
Wondering how to get field state from multiple fields at once?
People coming from Redux-Form might be wondering where the equivalent of Redux Form's Fields
component is, as a way to get state from several fields at once. The answer is that it's not included in the library because it's so easy to write one recursively composing Field
components together.
Calculated Fields
Demonstrates how to use the
final-form-calculate
decorator to achieve realtime field calculations through easily defined rules.
Field Warnings
Demonstrates how the power of subscriptions and mutators can be used to build a warning engine: logic to display a message next to each field that is not an error (thus it does not prevent form submission).
Reusable Field Groups
Demonstrates how fields can be grouped into reusable components.
External Submit
Demonstrates how you can use document.getElementById()
or a closure to trigger
a submit from outside of the form. For more information, see
How can I trigger a submit from outside the form?
Wizard Form
Demonstrates how to use π React Final Form to create a multi-page "wizard" form, with validation on each page.
Parse and Format (and Normalize)
Demonstrates how to use π React Final Form's parse
and format
props to control exactly how the data flows from the form state through the input and back to the form state. Notice that you can use parse
to "normalize" your values.
Auto-Save with Debounce
Demonstrates how to use a FormSpy
component to listen for value changes and automatically submit different values after a debounce period.
Auto-Save with Selective Debounce
Demonstrates how to use a FormSpy
component to listen for value changes and automatically submit different values after a debounce period, but only does the debounce for certain specified fields, in this case, all the text fields.
Auto-Save on Field Blur
Demonstrates how to use a FormSpy
component to listen for values and active field changes to automatically submit values when fields are blurred.
Custom Validation Engine
Demonstrates how incredibly extensible FormSpy
, the setFieldData
mutator, and render props are by implementing a custom validation engine completely apart from the built-in validation in π Final Form, thus allowing for special behaviors, like only validating a single field when that field is blurred.
Loading, Normalizing, Saving, and Reinitializing
Demonstrates how to make a wrapper component to handle loading, normalization of data, saving, and reinitializing of the form, to maintain pristine
/dirty
state with saved data.
ποΈ Downshift Type-Ahead
Demonstrates how to use a ποΈ Downshift type-ahead component as an input.
Redux Example
The only reason to keep your π Final Form form data in Redux is if you need to be able to read it from outside your form. This example demonstrates how to use a FormSpy
to keep a copy of your form data in the Redux store. Note that the canonical authoritative version of the data still lives in π Final Form. If you need to mutate your data via dispatching Redux actions, you should probably use Redux Form.
Conditional Fields
Sometimes you might want to conditionally show or hide some parts of your form depending on values the user has already provided for other form inputs. π React Final Form makes that very easy to do by creating a Condition
component out of a Field
component.
Listening for External Changes
By wrapping a stateful ExternalModificationDetector
component in a Field
component, we can listen for changes to a field's value, and by knowing whether or not the field is active, deduce when a field's value changes due to external influences.
Focus On First Error
Demonstrates how to incorporate the π Final Form Focus π§ decorator to provide this functionality out of the box.
Credit Card Example
Demonstrates how to make an awesome credit card UX using React Credit Cards.
Async Redux Submission
Want to use redux-saga
or redux-observable
to manage your form submissions? Now you can, using react-redux-promise-listener
to convert your dispatched Redux actions into the Promise
that π React Final Form is expecting for its onSubmit
function.
Declarative Form Rules
What if you could define rules to update fields when other fields change as components? This example explores such possibilities. There's also a Medium post about writing it, and creating a companion library, react-final-form-listeners
.
Format String By Pattern
Demonstrates how to use the library format-string-by-pattern
to create input masks for your π React Final Form fields.
AsyncTypeahead and Redux
Demonstrates creating an AsyncTypeahead
to select github users, while storing the search results in the redux store and the form state (selected github users) via react-final-form
. Also makes use of the setFieldData
mutator.
Format On Blur
Demonstrates how to use the formatOnBlur
prop to postpone the formatting of a form field value until the field loses focus. Very useful for formatting numbers, like currencies.
Styling with π Smooth-UI
Demonstrates how to use the Smooth-UI styling library to make your forms look fabulous! All you really need is a higher order component that adapts The π Smooth-UI form controls to work with π React Final Form.
Rendering
There are three ways to tell <Form/>
and <Field/>
what to render:
| Method | How it is rendered |
| ------------------------------- | --------------------------------------------------------- |
| component
prop | return React.createElement(this.props.component, props)
|
| render
prop | return this.props.render(props)
|
| a render function as children
| return this.props.children(props)
|
API
The following can be imported from react-final-form
.
Field : React.ComponentType<FieldProps>
A component that takes FieldProps
and renders an individual
field.
Form : React.ComponentType<FormProps>
A component that takes FormProps
and surrounds your entire form.
FormSpy : React.ComponentType<FormSpyProps>
A component that takes FormSpyProps
and can listen to form
state from inside an optimized <Form/>
.
version: string
The current used version of π React Final Form.
Types
FieldProps
These are props that you pass to
<Field/>
. You must provide one of the
ways to render: component
, render
, or children
.
allowNull?: boolean
By default, if your value is null
, <Field/>
will convert it to ''
, to
ensure
controlled inputs.
But if you pass true
to allowNull
, <Field/>
will give you a null
value.
Defaults to false
.
children?: ((props: FieldRenderProps) => React.Node) | React.Node
A render function that is given FieldRenderProps
, as well
as any non-API props passed into the <Field/>
component.
component?: React.ComponentType<FieldRenderProps> | string
A component that is given FieldRenderProps
as props, children and render props, as
well as any non-API props passed into the <Field/>
component.
defaultValue?: any
β οΈ You probably want initialValue
! β οΈ
Before using this prop, read and understand the π Final Form documentation on initialValue
and defaultValue
!
format?: ((value: any, name: string) => any) | null
A function that takes the value from the form values and the name of the field and formats the value to give to the input. Common use cases include converting javascript Date
values into a localized date string. Almost always used in conjunction with parse
.
Note: If you pass null
to format
, it will override the default behavior of converting undefined
into ''
. If you do this, making sure your inputs are "controlled" is up to you.
formatOnBlur?: boolean
If true
, the format
function will only be called when the field is blurred. If false
, format
will be called on every render. Defaults to false
.
initialValue?: any
[See the π Final Form docs on initialValue
](https://github.com/final-form/final-form# #initialvalue-any)
isEqual?: (a: any, b: any) => boolean
See the π Final Form docs on isEqual
.
name: string
The name of your field. Field values may be deeply nested using dot-and-bracket syntax. Learn more about Field Names.
parse?: ((value: any, name: string) => any) | null
A function that takes the value from the input and name of the field and converts the value into the value you want stored as this field's value in the form. Common usecases include converting strings into Number
s or parsing localized dates into actual javascript Date
objects. Almost always used in conjuction with format
.
Note: If you pass null
to parse
, it will override the default behavior of converting ''
into undefined
, thus allowing you to have form values of ''
.
render?: (props: FieldRenderProps) => React.Node
A render function that is given FieldRenderProps
, children prop, as well
as any non-API props passed into the <Field/>
component.
subscription?: FieldSubscription
A
FieldSubscription
that selects all of the items of
FieldState
that you
wish to update for. If you don't pass a subscription
prop, it defaults to
all of FieldState
.
validate?: (value: ?any, allValues: Object, meta: ?FieldState) => ?any
A function that takes the field value, all the values of the form and the meta
data about the field and
returns an error if the value is invalid, or undefined
if the value is valid.
validateFields?: string[]
See the π Final Form docs on validateFields
.
value?: any
This is only used for checkboxes and radio buttons!
- Radio Buttons: The value of the radio button. The radio button will render as
checked
if and only if the value given here===
the value for the field in the form. - Checkboxes:
value
is specified: the checkbox will bechecked
if the value given invalue
is contained in the array that is the value for the field for the form. Checking the box will add the value to the array, and unchecking the checkbox will remove the value from the array.- no
value
is specified: the checkbox will bechecked
if the value is truthy. Checking the box will set the value totrue
, and unchecking the checkbox will set the value tofalse
.
FieldRenderProps
These are the props that <Field/>
provides to your render function or component. This object separates out the
values and event handlers intended to be given to the input component from the
meta
data about the field. The input
can be destructured directly into an
<input/>
like so: <input {...props.input}/>
. Keep in mind that the values
in meta
are dependent on you having subscribed to them with the
subscription
prop
input.name: string
The name of the field.
input.onBlur: (?SyntheticFocusEvent<*>) => void
The onBlur
function can take a SyntheticFocusEvent
like it would if you had
given it directly to an <input/>
component, but you can also just call it:
props.input.onBlur()
to mark the field as blurred (inactive).
input.onChange: (SyntheticInputEvent<*> | any) => void
The onChange
function can take a SyntheticInputEvent
like it would if you
had given it directly to an <input/>
component (in which case it will read the
value out of event.target.value
), but you can also just call it:
props.input.onChange(value)
to update the value of the field.
input.onFocus: (?SyntheticFocusEvent<*>) => void
The onFocus
function can take a SyntheticFocusEvent
like it would if you had
given it directly to an <input/>
component, but you can also just call it:
props.input.onFocus()
to mark the field as focused (active).
input.value: any
The current value of the field.
meta.active?: boolean
See the π Final Form docs on active
.
meta.data?: Object
See the π Final Form docs on data
.
meta.dirty?: boolean
See the π Final Form docs on dirty
.
meta.error?: any
See the π Final Form docs on error
.
meta.initial?: any
See the π Final Form docs on initial
.
meta.invalid?: boolean
See the π Final Form docs on invalid
.
meta.modified?: boolean
See the π Final Form docs on modified
.
meta.pristine?: boolean
See the π Final Form docs on pristine
.
meta.submitError?: any
See the π Final Form docs on submitError
.
meta.submitFailed?: boolean
See the π Final Form docs on submitFailed
.
meta.submitSucceeded?: boolean
See the π Final Form docs on submitSucceeded
.
meta.submitting?: boolean
See the π Final Form docs on submitting
.
meta.touched?: boolean
See the π Final Form docs on touched
.
meta.valid?: boolean
See the π Final Form docs on valid
.
meta.visited?: boolean
See the π Final Form docs on visited
.
FormProps
These are the props that you pass to
<Form/>
. You must provide one of the
ways to render: component
, render
, or children
.
children?: ((props: FormRenderProps) => React.Node) | React.Node
A render function that is given FormRenderProps
, as well
as any non-API props passed into the <Form/>
component.
component?: React.ComponentType<FormRenderProps>
A component that is given FormRenderProps
as props, as
well as any non-API props passed into the <Form/>
component.
debug?: DebugFunction
See the π Final Form docs on debug
.
decorators?: Decorator[]
Decorator
s
to apply to the form.
initialValues?: Object
See the π Final Form docs on initialValues
.
initialValuesEqual?: (?Object, ?Object) => boolean
A predicate to determine whether or not the initialValues
prop has changed. Useful for passing in a "deep equals" function if you need to. Defaults to "shallow equals".
keepDirtyOnReinitialize?: boolean
See the π Final Form docs on keepDirtyOnReinitialize
.
mutators?: { [string]: Mutator }
See the π Final Form docs on mutators
.
onSubmit: (values: Object, form: FormApi, callback: ?(errors: ?Object) => void) => ?Object | Promise<?Object> | void
See the π Final Form docs on onSubmit
.
render?: (props: FormRenderProps) => React.Node
A render function that is given FormRenderProps
, as well
as any non-API props passed into the <Form/>
component.
subscription?: FormSubscription
A
FormSubscription
that selects all of the items of
FormState
that you wish
to update for. If you don't pass a subscription
prop, it defaults to all of
FormState
.
validate?: (values: Object) => Object | Promise<Object>
See the π Final Form docs on validate
.
validateOnBlur?: boolean
See the π Final Form docs on validateOnBlur
.
FormRenderProps
These are the props that <Form/>
provides to your render function or component. Keep in mind that the values you
receive here are dependent upon which values of
FormState
you have
subscribed to with the
subscription
prop.
This object contains everything in
π Final Form's FormState
as well as:
batch: (fn: () => void) => void)
[DEPRECATED] Use form.batch()
instead
A function that allows batch updates to be done to the form state.
See the π Final Form docs on batch
.
blur: (name: string) => void
[DEPRECATED] Use form.blur()
instead
A function to blur (mark inactive) any field.
change: (name: string, value: any) => void
[DEPRECATED] Use form.change()
instead
A function to change the value of any field.
focus: (name: string) => void
[DEPRECATED] Use form.focus()
instead
A function to focus (mark active) any field.
form: FormApi
The π Final Form FormApi
.
handleSubmit: (?SyntheticEvent<HTMLFormElement>) => void
A function intended for you to give directly to the <form>
tag: <form onSubmit={handleSubmit}/>
.
initialize: (values: Object) => void
[DEPRECATED] Use form.initialize()
instead
A function that initializes the form values.
See the π Final Form docs on initialize
.
mutators?: { [string]: Function }
[DEPRECATED] Use form.mutators
instead
See the π Final Form docs on mutators
.
reset: (newInitialValues?: Object) => void
[DEPRECATED] Use form.reset()
instead
A function that resets the form values to their last initialized values.
See the π Final Form docs on reset
.
FormSpyProps
These are the props that you pass to
<FormSpy/>
. You must provide one
of the ways to render: component
, render
, or children
.
children?: ((props: FormSpyRenderProps) => React.Node) | React.Node
A render function that is given FormSpyRenderProps
, as
well as any non-API props passed into the <FormSpy/>
component. Will not be
called if an onChange
prop is provided.
component?: React.ComponentType<FormSpyRenderProps>
A component that is given FormSpyRenderProps
as props,
as well as any non-API props passed into the <FormSpy/>
component. Will not be
called if an onChange
prop is provided.
onChange?: (formState: FormState) => void
A change listener that will be called with form state whenever the form state,
as subscribed to by the subscription
prop, has changed. When an onChange
prop is provided, the <FormSpy/>
will not render anything.
render?: (props: FormSpyRenderProps) => React.Node
A render function that is given FormSpyRenderProps
, as
well as any non-API props passed into the <FormSpy/>
component. Will not be
called if an onChange
prop is provided.
subscription?: FormSubscription
A
FormSubscription
that selects all of the items of
FormState
that you wish
to update for. If you don't pass a subscription
prop, it defaults to all of
FormState
.
FormSpyRenderProps
These are the props that
<FormSpy/>
provides to your render
function or component. These props are of type
FormState
. Keep in mind
that the values you receive here are dependent upon which values of
FormState
you have
subscribed to with the
subscription
prop. Also included will be many of the same props provided to FormRenderProps
:
batch: (fn: () => void) => void)
[DEPRECATED] Use form.batch()
instead
A function that allows batch updates to be done to the form state.
See the π Final Form docs on batch
.
blur: (name: string) => void
[DEPRECATED] Use form.blur()
instead
A function to blur (mark inactive) any field.
change: (name: string, value: any) => void
[DEPRECATED] Use form.change()
instead
A function to change the value of any field.
focus: (name: string) => void
[DEPRECATED] Use form.focus()
instead
A function to focus (mark active) any field.
form: FormApi
The π Final Form FormApi
.
initialize: (values: Object) => void
[DEPRECATED] Use form.initialize()
instead
A function that initializes the form values.
See the π Final Form docs on initialize
.
mutators?: { [string]: Function }
[DEPRECATED] Use form.mutators
instead
See the π Final Form docs on mutators
.
reset: (newInitialValues?: Object) => void
[DEPRECATED] Use form.reset()
instead
A function that resets the form values to their last initialized values.
See the π Final Form docs on reset
.
Contributors
This project exists thanks to all the people who contribute. [Contribute].
Backers
Thank you to all our backers! π [Become a backer]
Sponsors
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]