TIP: Open react developer tools, go to preferences and enable Highlight updates and then start typing on the form inputs to see which components update.
import React, { useRef } from 'react'
import { useFieldState, useForm, useFormState } from 'react-form-hooks'
/**
This is an example where everything is defined in a single component.
This may be fine for getting started. But it can become cumbersome to manage
especially when working with large number of inputs.
Also, when using hooks, the component hosting the hook will be re-rendered
whenever the state is updated like the field and form state here.
For large forms, the form would perform better if the hooks are moved to their
own components and then reused.
Check the BasicExample example for a sample pattern to reuse code.
*/
function MyForm() {
// useRef is necessary here because otherwise, the form will be reset
// when initialValues reference changes on re-render.
const initialValues = useRef({ name: 'John' }).current
const form = useForm({ initialValues })
const formState = useFormState(form)
const { anyError, anyDirty, anyTouched, values, errors } = formState
const nameState = useFieldState(form, 'name')
const ageState = useFieldState(form, 'age', undefined, {
validate: value => value < 18 && 'age should be above 18',
})
const emailState = useFieldState(form, 'email', undefined, {
validate: v => !/^\S+@\S+\.\S+$/.test(v) && 'should be a valid email',
})
const onSubmit = values => alert(JSON.stringify(values, null, 2))
return (
<form onSubmit={form.formActions.submitHandler(onSubmit)}>
<div>
<label htmlFor="name">Name</label>
<input
id="name"
onChange={e =>
form.fieldActions.changeFieldValue(
'name',
e.target.value.toUpperCase()
)
}
onBlur={() => form.fieldActions.touchField('name')}
value={nameState.value}
/>
</div>
<div>
<label htmlFor="age">Age</label>
<input
id="age"
type="number"
onChange={e =>
form.fieldActions.changeFieldValue(
'age',
e.target.value.toUpperCase()
)
}
onBlur={() => form.fieldActions.touchField('age')}
value={ageState.value}
/>
</div>
<div>
<label htmlFor="email">Email</label>
<input
id="email"
onChange={e =>
form.fieldActions.changeFieldValue('email', e.target.value)
}
onBlur={() => form.fieldActions.touchField('email')}
value={emailState.value}
/>
</div>
<pre>{JSON.stringify(values, null, 2)}</pre>
<pre>{JSON.stringify(errors, null, 2)}</pre>
{anyError && <div>Form Error</div>}
{anyDirty && <div>Form Dirty</div>}
{anyTouched && <div>Form Touched</div>}
<button type="submit">Submit</button>
<button onClick={() => form.formActions.resetFormValues()}>Reset</button>
</form>
)
}
export default MyForm