De-Formed is a library for designing modular, event-driven form and data validations. Bind the things you need; ignore the things you don't. De-Formed will take care of the rest so that you can design your architecture the way you want to.
- Modular - decoupled from your form architecture.
- Composable - turn your validations and forms into Lego bricks.
- Extendable - add/modify the API as you see fit
- Unopinionated - customize your UX to the Moon ๐
- Lightweight - compare it on bundlephobia
- Easy to Use - its all functions
- Easy to Test - unit test your business logic
- Yup Compatible - can integrate with your existing yup schemas
yarn add @de-formed/react-validations
npm i @de-formed/react-validations
// usePersonValidation.ts
import { useValidation } from '@de-formed/react-validations';
export const usePersonValidation = () => {
return useValidation<Person>({
firstName: [
{
error: 'First Name is required.',
validation: ({ firstName }) => firstName.length > 0,
},
],
lastName: [
{
error: 'Last Name is required.',
validation: ({ lastName }) => lastName.length > 0,
},
],
});
};
Bind the things you need; ignore the things you don't. De-Formed will take care of the rest.
// PersonForm.component.tsx
import React from 'react';
import { usePersonValidation } from './usePersonValidation';
export const PersonForm = ({ person, onChange }) => {
const {
getError,
validateAll,
validateOnChange,
validateOnBlur
} = usePersonValidation();
const handleSubmit = () => {
if (validateAll(person) {
// submit logic
}
};
return (
<>
<div>
<label>First Name</label>
<input
name="firstName"
onBlur={validateOnBlur(person)}
onChange={validateOnChange(onChange, person)}
value={person.firstName}
/>
{getError('firstName') && <p>{getError('firstName')}</p>}
</div>
<div>
<label>Last Name</label>
<input
name="lastName"
onBlur={validateOnBlur(person)}
onChange={validateOnChange(onChange, person)}
value={person.lastName}
/>
{getError('lastName') && <p>{getError('lastName')}</p>}
</div>
<button onClick={handleSubmit}>Submit</button>
</>
);
};
The validation schema is on object that defines a list of validation rules for
any given key. Each validation rule consists of the error
to display to a
user and a function that returns true or false. Error messages can be passed a
function to generate dynamic error messages depending on the state of the data.
Keys that match the keys of an object will be automatically detected when using
validateAll
.
{
email: [
{
error: 'Email is required.',
validation: ({ email }) => email.trim().length > 0,
},
{
error: ({ email }) => `${email} must be a valid email.`,
validation: ({ email, name }) =>
name === 'bob ross' ? email === '[email protected]' : true
},
],
}
Auto-props are functions that apply simple validation rules for strings and numbers.
type Person = {
name: string
age: number
agreement: boolean
}
const personValidation = () => {
return Validation<Person>({
name: [required(), shorterThan(12)],
age: [min(42), max(100)],
agreement: [is(true, 'Must accept terms.')],
})
}
Guided walkthrough of how to customize De-Formed to the moon ๐
API documentation.
More examples and CodeSandboxes.
This project is licensed under the terms of the MIT license.