Tired of writing custom form validation on every project you might work on? Letβs try hocForm, form validation on React has rarely been so simple! π€
Requirements
hocForm needs at least react@16.3.1 and react-dom@16.3.1 to work.
Installation
Using npm:
npm install --save hoc-form
yarn add hoc-form works fine too!
Usage
import React from 'react'; import hocForm, { Field } from 'hoc-form'; // First, we need a input component to render our text field function Input({ input = {}, label = '', meta = {}, placeholder = '', type = 'text', }) { return ( <div> <label> {label} </label> <input placeholder={placeholder} type={type} {...input} onBlur={e => input.onBlur && input.onBlur(e.target.value)} onChange={e => input.onChange(e.target.value)} /> {meta.error && <span>{meta.error}</span>} </div> ); } // Then, we need to create our form component and its helpers const unavailableUsernames = [ 'elonmusk', 'ironman', 'lukeskywalker', ]; function validateLogin(value = '') { if (value.trim() === '') { return Promise.reject('Please enter an username'); } return unavailableUsernames.includes(value) ? Promise.reject('This username is unavailable') : Promise.resolve() } function validatePassword(value = '') { if (value.trim().length < 6) { return Promise.reject('Password must contain 6 characters or more'); } return Promise.resolve(); } function Form({ onSubmit }) { return ( <form onSubmit={onSubmit} noValidate> <Field name="login" component={Input} props={{ label: 'Login *', onBlur: value => validateLogin(value), placeholder: 'elonmusk', type: 'string', }} /> <Field name="pwd" component={Input} props={{ label: 'Password *', type: 'password', }} /> <button type="submit">Sign up</button> </form> ); } // Finally, an export of our wrapped form component // with a validation function export default hocForm({ validate(values, props) { let errors = {}; const errorCatcher = (key, callback, ...args) => ( callback(values[key], args) .catch(error => ({ [key]: error })) ); return Promise.all([ errorCatcher('login', validateLogin), errorCatcher('pwd', validatePassword), ]).then((errors) => { const results = errors.reduce((acc, item) => ({ ...acc, ...item }), {}); return Object.keys(results).length ? Promise.reject(results) : Promise.resolve(); }); } })(Form);
Please check out the complete demo! π
API
hocForm({ options })(MyFormComponent) => React.Component
Renders your MyFormComponent contexted with hocForm.
Two arguments are required:
- An
optionsobject to define thevalidatefunction and optionalinitialValues - A form
React.Componentto render.
options.validate(values, props) => Promise
Validates the form on submit.
Arguments:
values(Object): An object containing all fields keys and their value.props(Object): An object containing all props provided toMyFormComponent.
Returns:
- A promise:
- On success, your must return
Promise.resolve() - In case of failure, your must return
Promise.reject({}). The object parameter must contain every field key with its error (type of string or else, depends on how your components used withFieldare designed).
- On success, your must return
Example, with errors as strings:
function validate(values, props) { let errors = {}; if (values.username) { if (!props.isUsernameAvailable(values.username)) { errors = { ...errors, username: 'This username is unavailable' }; } } else { errors = { ...errors, username: 'Please enter an username' }; } if (!values.password) { errors = { ...errors, password: 'Please enter a password' }; } return Object.keys(errors).length ? Promise.reject(errors) : Promise.resolve(); }
options.initialValues: Object
Object containing all initial values following fields keys.
Example:
initialValues: { country: 'United Kingdom', phone: '+44', }
MyFormComponent: React.Component
A React.Component rendering a form including some hocForm.Field items.
Example:
"function Form({ onSubmit }) {
return (