Building highly performant forms is the duty of React Cool Form. It minimizes the number of re-renders and provides the best user experience by the following features:
- No unnecessary re-renders by leveraging the power of uncontrolled components
- No unnecessary re-renders when using the form state
- No unnecessary re-renders when receives the same form state (since last re-rendering)
- Filters the errors of untouched fields for better UX (refer to the UX research at No.7)
Here we will explore the form state and some best practices for using it.
Form state is an
object containing the following properties:
|values||The current values of the form.|
|errors||The current validation errors. The shape will (should) match the shape of the form's values.|
|touched||An object containing all the fields the user has touched/visited.|
|dirty||An object containing all the fields the user has modified.|
|submitCount||Number of times the user tried to submit the form. The value will remain until the form is reset.|
React Cool Form provides a powerful API: use to help us avoid unnecessary re-renders when using the form state.
We can construct an array/object with multiple state-picks inside like the following example:
Every time we get a value from the form state via the
use method, it will listen the changes of the value and trigger re-renders only when necessary. Thus, there're some guidelines for us to use the form state. General speaking, more frequently updated value(s), need to be accessed more specific, will get more performant.
The form's values might be the most frequent one that we need to get in a specific way, it's kind of verbose. However there's a shortcut for it, we can get the form's values without the
If we didn't initialize the default value of a field via the defaultValues option of the
use method will lose the value. Because the method is called before the field's initial render. For such cases, we can provide an alternative default value for the
use method to return as below:
If you need to refer to the status of a conditional field, we recommend to use React state instead.
Error messages are dependent on the form's validation (i.e. the
errors object). To avoid annoying the user by seeing an error message while typing, we can filter the errors of untouched fields by enable the
errorWithTouched option (default is
This feature filters any errors of the untouched fields. So when validating with the runValidation, please ensure it's triggered after the field(s) is (are) touched.
👉🏻 See the Displaying Error Messages to learn more about it.
Whenever a monitored value of the form state is updated, it will trigger re-renders. Re-renders are not bad but slow re-renders are (refer to the article). So, if you are building a complex form with large number of fields, you can isolate re-rendering at the component level via the useFormState hook for better performance. The hook has the similar API design to the
use method that maintain a consistent DX for us.
We must provide a valid path to use the hook, or it will return
useFormState hook can also play as an event listener to listen for the changes to properties in the form state without triggering re-renders.
We must provide a valid path to use the hook, or the callback won't be triggered.
If you just want to read the form state without triggering re-renders, there's a getState method for you.
Please note, this method should be used in an event handler.
With the method, we can read/construct the data by the following ways: