React Final Form
compare with redux form
redux-form
formik
final-form
npm trend
Redux form
- redux needed
- Field, Fields, FieldArray
- Higher-order component
- handle by redux
- Up to 27 KB gzipped
React Final form
- final-form needed
- Field (need other helpers)
- Render props
- Subscription based
- Light weighted
- redux-form like
APIs
- Form
- Field
- FormSpy
- useForm
- useField
- useFormState
react-final-form
final-form
- FORM_ERROR
Form
import { Form } from 'react-final-form';
function BasicForm() {
return (
<Form
onSubmit={(values) => {
const {
name,
email,
} = values;
}}
initialValues={{
name: 'Stanney',
email: 'rytass@rytass.com',
}}
validate={(values) => {
const errors = {};
if (!values.name) errors.name = 'Required';
return errors;
}}>
{({
submitError,
handleSubmit,
}) => (
/* form view */
)}
</Form>
);
}
Field
import { Field } from 'react-final-form';
function BasicFormView({
handleSubmit,
submitError,
}) {
return (
<form onSubmit={handleSubmit}>
<Field
name="name"
component={Input} />
{submitError ? (
<span>{submitError}</span>
) : null}
</form>
);
}
function Input({
input: {
value,
onChange,
},
meta: {
error, // validate error
submitError, // submit error
},
}) {
/* input view */
}
Errors handle
import { FORM_ERROR } from 'final-form';
<Form
onSubmit={(values) => {
const {
name,
email,
} = values;
if (name !== 'rytass') {
return {
name: 'Wrong name.',
};
}
if (!email.match(emailReg)) {
return {
[FORM_ERROR]: 'Wrong Email format',
};
}
return null;
}}
validate={(values) => {
const errors = {};
if (!values.name) errors.name = 'Required';
return errors;
}}>
</Form>
Field component
=> meta.submitError
Form render props
=> submitError
Field component
=> meta.error
Re-render problem
Form without subscription causing component re-render every field changes
<Form
onSubmit={onSubmit}
initialValue={myInits}>
{({
values,
handleSubmit,
submitError,
}) => (
/* form view */
)}
</Form>
<Form
onSubmit={onSubmit}
initialValue={myInits}
subscription={{
submitting: true,
}}>
{({
values,
handleSubmit,
submitError,
}) => (
/* form view */
)}
</Form>
Form Spy
subscribe on Form props (must under Form component)
import { Form, FormSpy } from 'react-final-form';
<Form
subscription={{
submitting: true,
}}>
{({
values,
}) => (
/* form view */
<FormSpy subscription={{ values: true }}>
{({
values,
}) => (
/* re-render every field value change */
)}
</FormSpy>
)}
</Form>
Field composing
import { Form, Field } from 'react-final-form';
<Form
subscription={{
submitting: true,
}}>
{({
values,
}) => (
/* form view */
<Field name="cityId">
{({
input: { value, onChange },
}) => {
const currentCity = cityZones.find(c => c.id === value) || null;
return (
<Field
name="zoneId"
options={currentCity ? currentCity.zones : []}
component={Selector} />
);
}}
</Field>
)}
</Form>
Field need to bind with other Field (value change, onChange)
Helpers
I want...
- Fields composing Field yourself
- FieldArray use react-final-form-arrays
- Wizard Form (multipage form)
DEMO
React final form
By Travor Lee
React final form
compare with redux form
- 171