react-use-form-hooks
React hooks for managing form state. Uses React Hooks API to manage common form elements state. The hooks are meant to be generic and usefull.
Requires react@^16.8.0 react-dom@^16.8.0
as peer dependencies.
Features
- Keeps field value state
- Keeps field touched state
- Keeps field validation state
- Executes validation and exposes validation errors
- Will support async validation (TODO)
Installation
npm
npm i --save react-use-form-hooks
yarn
yarn add react-use-form-hooks
Usage
Example:
;; { const fieldOne = ; const fieldTwo = ; const form = ; return <form onSubmit=formhandleSubmit> <MyInput label="Field One" type="text" value=fieldOnevalue required=fieldOneisRequired onChange=fieldOnehandleChange isValid=fieldOneisValid isTouched=fieldOneisTouched validationErrors=fieldOnevalidationErrors successfulValidations=fieldOnesuccessfulValidations /> <MyInput label="Field Two" type="can be anything really" value=fieldTwovalue required=fieldTwoisRequired onChange=fieldTwohandleChange isValid=fieldTwoisValid isTouched=fieldTwoisTouched validationErrors=fieldTwovalidationErrors successfulValidations=fieldTwosuccessfulValidations /> <button type="submit" disabled=!formisSubmittable> Submit </button> </form> ;}
API
The module exports two hooks: useFormField
and useFormWithFields
.
useFormField
const field = ;
Returns object with following fields:
isEmpty // boolean; indicates whether field value is empty isRequired // boolean isTouched // boolean; indicates whether field value has been changed isValid // boolean; indicates whether field value is valid isAcceptable // boolean; indicates whether field is known to be OK to be used in form data submission handleChange // function; should be called on controlled input change if it should be validated immediately handleChangeValueOnly // function; should be called on controlled input change if it should NOT be validated immediately. Field will be validated on blur or submission attempt instead handleReset // function; reset field to initial state handleClear // function; clear field value handleSubmitAttempt // function: Called by useFormWithFields hook. May be called manually on form submit attempt if useFormWithFields is not used successfulValidations // array of successful validations results validationErrors // array of failed validation results / validation error messages value //any; field value
Parameters
accessor // function or string, optional adapter // function, optional emptyValue // any, optional initialValue // any, optional, default is empty string isRequired // boolean, optional, default is false validate // function, optional validateRequired // function, optional
accessor
Optional. Used to extract field value out of object passed as a parameter to handleChange
and handleChangeValueOnly
handlers.
If accessor is a string, it is used as a path to object's value.
If accessor is a function it is expected to return the new value.
Note: if no acessor is provided, the hook will first attempt to treat parameter as event and resolve it's 'target.value' path. In case if 'target.value' path returns undefined, the raw param will used as value.
adapter
Optional. Used to supplement field values. For example, to produce a shape that can be fed to bootstap components. The function only needs to return the new fields.
emptyValue
Optional. Value that will be set on field clear with handleClear
.
initialValue
Optional. Defaults to empty string. Initial value. Will also be set on field reset with handleReset
.
isRequired
Optional. If true, field will be treated as not OK for submission when empty.
validate
Optional. Function that is used to validation the field.
validateRequired
Optional. Function that is used to check if field is empty. Should return error message or any truthy value if field is empty and a falsy value otherwise. Defaults to a function that returns truthy for undefined
, null
, ''
and [] values.
useFormWithFields
const field1 = ;const field2 = ;const form = ;
Returns object with following fields:
isSubmittable // boolean; indicates whether all form fields are OK isSubmitAttempted // boolean; indicates whether handleSubmit has been called at least once handleSubmit // function to be called on form submission attempt
Parameters
onSubmit // function; called on submit attempt if all fields are OK onFailedSubmit // function; called on submit attempt if at least one field is not OK fields // array of return values of useFormField hooks
onSubmit
Optional. If supplied, it will be called with the param (usually event) passed to the handleSubmit
handler only if all fields listed in fields
param are OK.
onFailedSubmit
Optional. If supplied, it will be called with the param (usually event) passed to the handleSubmit
handler only if at least one field listed in fields
param is not OK.
Defaults to function that prevents default event handling.
fields
Required. Array of objects produced by useFormField
hooks.
Validation
Simple form
validate
function may return an error message if validation fails and any falsy value if it succeeds.
Example:
valuelength < 5 ? 'Value must be at least 5 characters long' : null
When above validation fails, the field shape will have keys:
successfulValidations: validationErrors: 'Value must be at least 5 characters long' isInvalid: true isValid: false ...other
When above validation succeeds, the field shape will have keys:
successfulValidations: validationErrors: isInvalid: false isValid: true ...other
Note: since in this form validate
only returns errorMessage on failure, successfulValidations
will always be an empty array.
Multiple errors
There may be multiple problems with the value that is being validated and it may be a good idea to let user know of all of them instead of presenting only one at a time.
validate
function may return an array of validation error messages.
A good example is a password field:
{ const errorMessages = ; if passwordlength < 5 errorMessages; if !RegExp/.*[A-Z]+.*/g errorMessages; if !RegExp/.*[a-z]+.*/g errorMessages; return errorMessages;}
When above validation fails, the field shape will have keys:
// ex. value = 'test'; successfulValidations: validationErrors: 'Password must be at least 5 characters long' 'Password must include at least one uppercase letter' isInvalid: true isValid: false ...other
When above validation succeeds, the field shape will have keys:
successfulValidations: validationErrors: isInvalid: false isValid: true ...other
Note: since in this form validate
only returns errorMessages, successfulValidations
will always be an empty array.
Successful Validations
If you would like to be explicit about what validations suceeded, validate
function may return an array with two items in it: [validationErrors, successfulValidations]
.
First item is an array of validation error messages.
The second item is an array of successful validation messages.
Example:
{ const errorMessages = ; const successfulValidations = ; if passwordlength < 5 errorMessages; else successfulValidations; if !RegExp/.*[A-Z]+.*/g errorMessages; else successfulValidations; if !RegExp/.*[a-z]+.*/g errorMessages; else successfulValidations; return errorMessages successfulValidations;}
When above validation fails, the field shape will have keys:
// ex. value = 'test'; successfulValidations: 'Password has a lowercase letter' validationErrors: 'Password must be at least 5 characters long' 'Password must include at least one uppercase letter' isInvalid: true isValid: false ...other
When above validation succeeds, the field shape will have keys:
successfulValidations: 'Password is long enough' 'Password has an uppercase letter' 'Password has a lowercase letter' validationErrors: isInvalid: false isValid: true ...other
Async validation
In some cases validation requires an async operation. For example, making an API call to check if username is taken.
COMING SOON
Validating dependant fields
Sometimes, field validation depends on another field. A simple example is a password repeat field that needs to compare repeat field value to password field value.
This is where react hooks
shine: if both fields are in scope of the same functional component, value of one field can be accessed in validate
function of another.
Example:
{ const password = ; // no validation for simplicity const passwordRepeat = ;}
To validate both fields:
{ const password = ; const passwordRepeat = ; { return value !== passwordRepeat ? 'Passwords must match' : null; } { return value !== password ? 'Passwords must match' : null; }}
Development and contributions
yarn
git clone https://github.com/AntonRublev360/react-use-form-hooks.git
cd react-use-form-hooks
yarn install
yarn start
npm
git clone https://github.com/AntonRublev360/react-use-form-hooks.git
cd react-use-form-hooks
npm i
npm start
License
MIT