- ⚡ Fast input rerenders - doesn't rerender whole form
- 🥓 Well cooked api
- 👌 Form validation based on yup
- ⚖ It's lightweight
npm install --save @smashing/form mobx mobx-react-lite
import * as React from 'react'
import {useForm} from '@smashing/form'
const CustomTextInput = props => <input type="text" {...props} />
export const MyForm = () => {
// Use `useForm` hook. `initialValues` is the only required value.
const {Form, Field, form} = useForm({
initialValues: {
email: '',
password: '',
},
onSubmit: values => console.log(values),
})
// Wrap your inputs with `Form` returned by `useForm`
return (
<Form>
{/* Each input should be wrapped in `Field` returned by `useForm` */}
<Field component={CustomTextInput} name="email" />
{/* "input" is default component used by field */}
<Field name="password" />
<button type="submit">Submit</button>
</Form>
)
}
const {} = useForm({
initialValues,
validationSchema,
onSubmit,
validateOnBlur,
validateOnChange,
validateOnSubmit,
})
Object containing initial values of form. Can contain nested state.
Read yup docs to learn more.
Form submit handler
Control if data should be validated on input blur
Control if data should be validated on input change
Control if data should be validated on form submit
You can use yup to validate form data.
import * as React from 'react'
import * as yup from 'yup'
import {useForm} from '@smashing/form'
const TextInput = props => <input type="text" {...props} />
const validationSchema = yup.object().shape({
email: yup
.string()
.email('Email is not valid.')
.max(64, 'Email is too long.')
.required('This field is required.'),
password: yup
.string()
.min(6, 'Password is too short.')
.max(64, 'Password is too long.')
.required('This field is required.'),
})
export const MyForm = () => {
const {Form, Field, form} = useForm({
initialValues: {
email: '',
password: '',
},
validationSchema,
onSubmit: values => console.log(values),
})
return (
<Form>
<Field component={TextInput} name="email" />
<Field component={TextInput} name="password" />
<button type="submit">Submit</button>
</Form>
)
}
You can access whole state and form actions using form
property returned from useForm
.
const {form} = useForm({})
It contains the following state:
{
"isSubmitting": false,
"isValidating": false,
"isDirty": false,
"isValid": true,
"submitCount": 0,
"validateOnChange": false,
"validateOnBlur": false,
"validateOnSubmit": true,
"values": {},
"initialValues": {},
"errors": {},
"touched": {}
}
You can access form state using context. FormContext
and useFormContext
are exported from package.
import {useFormContext, FormContext} from '@smashing/form'
const NestedComponent = () => {
const {form} = useFormContext()
// OR const {form} = React.useContext(FormContext)
}
FormContext
/useFormContext
can be used only insideForm
component returned fromuseForm
.
const MyForm = () => {
const {Form, Field} = useForm({
initialValues: {
email: '',
social: {
twitter: '',
facebook: '',
},
friends: [{name: 'John'}, {name: 'Jane'}],
},
})
return (
<Form>
<Field component={TextInput} name="email" />
<Field component={TextInput} name="social.twitter" />
<Field component={TextInput} name="social.facebook" />
<Field component={TextInput} name="friends.0.name" />
<Field component={TextInput} name="friends.1.name" />
</Form>
)
}
Manipulating array items:
const {form} = useForm({
initialValues: {
friends: ['John', 'Jane'],
},
})
// Add new item
form.values.friends.push('')
// Remove first item
form.values.friends.splice(0, 1)
You can operate on form state using form
object returned by useForm
:
const {form} = useForm({
initialValue: {
email: '',
password: '',
},
})
form.setFieldValue('email', 'john.doe@example.com')
Rest form values, errors and touch states to initial state:
form.reset()
Optionally nextState
object can be passed:
form.reset({
values: {email: 'john.doe@example.com'},
errors: {password: 'Password is required'},
touched: {
email: true,
password: true,
},
})
Trigger onSubmit
handler.
Validate all inputs:
form.validate()
Validate single input:
form.validate('email')
Start or finish submission process:
form.setIsSubmitting(true)
Set all input values:
form.setValues({
email: '',
password: '',
})
Set all validation errors:
form.setErrors({
email: 'Email is invalid',
password: 'Password is to short',
})
Set all inputs touch state:
form.setTouched({
email: true,
password: false,
})
Set single field value:
form.setFieldValue('email', 'john.doe@example.com')
Set single field error message:
form.setFieldError('email', 'Email is invalid')
Set single field touch state:
form.setFieldTouched('email', true)
MIT © EYEDEA AS