use-lite-form
v1.0.78
Published
   => {
const [formResult, setFormResult] = useState(null);
const submit = payload => {
setFormResult(payload.value);
};
return (
<div>
<Form onSubmit={submit}>
<div>
<label>Full Name</label>
<Form.Item
path={['name']}
required
>
<input type='text' />
</Form.Item>
</div>
<div>
<label>Email</label>
<Form.Item
path={['email']}
required
>
<input type='email' />
</Form.Item>
</div>
<button type='submit'>Submit</button>
</Form>
{formResult && <pre>{JSON.stringify(formResult, null, 2)}</pre>}
</div>
);
};📖 API Reference
<Form>
The main component that provides the form context.
<Form
onSubmit={payload => console.log(payload.value)}
onChange={payload => console.log(payload.value, payload.errors)}
value={initialValues}
>
{/* Form content */}
</Form>Props
onSubmit: Function called when the form is submittedonChange: Function called when any form field changes (payload: Instance.Payload, action: Instance.Action)onErrorChange: Function called when any form field error changes (payload: Instance.Payload, action: Instance.Action)value: Initial form valuesform: Custom form instance (advanced usage)locked: Whether the form is locked for editingas: HTML element to render the form as (default: 'form')
<Form.Item>
Component for individual form fields.
<Form.Item
path={['user', 'name']}
required
defaultValue=''
>
<input type='text' />
</Form.Item>Props
childTransform: Transforms the value for the child component only, without affecting the form statepath: Array path specifying the location of this field's value within the form staterequired: Boolean or validation function that determines if the field is required and returns error messagesdefaultValue: Initial value used when the field has no value in the form statedebounce: Delay in milliseconds before reporting value changes to the form (default: 250ms)transformIn: Transforms the value when reading from form statetransformOut: Transforms the value when writing to form stateeffect: Side effect function executed whenever the field value changes in the form state
<Form.List>
Component for managing arrays of form items.
<Form.List path={['items']}>
<Form.List.Items>
{props => (
<div>
<Form.Item path={[...props.path, 'name']}>
<input type='text' />
</Form.Item>
<button onClick={() => props.remove()}>Remove</button>
</div>
)}
</Form.List.Items>
<Form.List.Add>{props => <button onClick={() => props.add({ name: '' })}>Add Item</button>}</Form.List.Add>
</Form.List><Form.Value>
Component to display or use form values in your UI.
<Form.Value path={['user', 'type']}>
{({ value }) => {
if (value === 'admin') {
return <div>Admin Fields...</div>;
}
return <div>User Fields...</div>;
}}
</Form.Value>Form.useForm()
Hook to access the form instance and values.
const MyComponent = () => {
const { instance, value } = Form.useForm(['user']);
// Access specific path value
console.log(value.name);
// Call form methods
instance.set(['user', 'name'], 'New Value');
return <div>...</div>;
};Form.useNewForm(initialValue?: object)
Hook to create a new form instance.
const MyComponent = () => {
const { instance, value } = Form.useNewForm({ name: 'Felipe' });
// Access specific path value
console.log(value.name);
// Call form methods
instance.set(['user', 'name'], 'New Value');
return <div>...</div>;
};Form.useFormHistory(options?: object)
A hook to manage the form's value history, enabling undo and redo functionality. It must be used within a <Form> component.
const HistoryControls = () => {
const { canRedo, canUndo, redo, undo, clear } = Form.useFormHistory({
maxCapacity: 20 // Optional: defaults to 10
});
return (
<div>
<button
onClick={undo}
disabled={!canUndo}
>
Undo
</button>
<button
onClick={redo}
disabled={!canRedo}
>
Redo
</button>
<button onClick={clear}>Clear History</button>
</div>
);
};
const MyForm = () => {
return (
<Form>
<HistoryControls />
{/* Form.Item fields go here */}
</Form>
);
};Options
maxCapacity(optional,number): The maximum number of history states to store. Defaults to10.debounceTime(optional,number): Time in milliseconds to debounce history updates.
Returns
canUndo(boolean): True if there is a past state to revert to.canRedo(boolean): True if there is a future state to restore.undo()(function): Reverts the form to the previous state.redo()(function): Restores the next state in the history.clear()(function): Clears the entire history.
🎯 Advanced Usage
Custom Validation
<Form.Item
path={['password']}
required={({ value }) => {
if (value.length < 8) {
return 'Password must be at least 8 characters';
}
if (!/[A-Z]/.test(value)) {
return 'Password must contain at least one uppercase letter';
}
if (!/[0-9]/.test(value)) {
return 'Password must contain at least one number';
}
return false;
}}
>
<input type='password' />
</Form.Item>Value Transformations
<Form.Item
path={['tags']}
defaultValue={[]}
transformIn={({ value }) => (Array.isArray(value) ? value.join(', ') : '')}
transformOut={({ value }) =>
value
.split(',')
.map(tag => tag.trim())
.filter(Boolean)
}
>
<input
type='text'
placeholder='tag1, tag2, tag3'
/>
</Form.Item>Conditional Rendering
<Form.Item
path={['contactMethod']}
defaultValue="email"
>
{/* Radio buttons for contact method */}
</Form.Item>
<Form.Value path={['contactMethod']}>
{({ value }) => {
if (value === 'email') {
return (
<Form.Item path={['emailAddress']} required>
<input type="email" />
</Form.Item>
);
}
if (value === 'phone') {
return (
<Form.Item path={['phoneNumber']} required>
<input type="tel" />
</Form.Item>
);
}
return null;
}}
</Form.Value>Dynamic Lists
<Form.List path={['items']}>
<Form.List.Items>
{props => (
<div>
<Form.Item
path={[...props.path, 'name']}
required
>
<input type='text' />
</Form.Item>
<Form.Item
path={[...props.path, 'quantity']}
defaultValue={1}
>
<input
type='number'
min='1'
/>
</Form.Item>
<div>
<button
onClick={() => props.moveUp()}
disabled={props.first}
>
Move Up
</button>
<button
onClick={() => props.moveDown()}
disabled={props.last}
>
Move Down
</button>
<button onClick={() => props.remove()}>Remove</button>
</div>
</div>
)}
</Form.List.Items>
<Form.List.Add>{props => <button onClick={() => props.add({ name: '', quantity: 1 })}>Add Item</button>}</Form.List.Add>
</Form.List>Undo/Redo with useFormHistory
Implement undo/redo functionality by creating a control component that uses the Form.useFormHistory hook.
import Form from 'use-lite-form';
// A component to manage history controls
const HistoryControls = () => {
const { canRedo, canUndo, redo, undo } = Form.useFormHistory();
return (
<div>
<button
type='button'
onClick={undo}
disabled={!canUndo}
>
Undo
</button>
<button
type='button'
onClick={redo}
disabled={!canRedo}
>
Redo
</button>
</div>
);
};
// The main form component
const EditorForm = () => (
<Form>
<HistoryControls />
<Form.Item
path={['title']}
debounce={500}
>
<input
type='text'
placeholder='Title'
/>
</Form.Item>
<Form.Item
path={['content']}
debounce={500}
>
<textarea placeholder='Start writing...' />
</Form.Item>
<button type='submit'>Save</button>
</Form>
);🧠 How It Works
use-lite-form is built around React's Context API to provide a seamless form management experience:
- Form Instance: Manages the form state, including values and errors
- Path-based Access: Uses array paths to access nested form data
- Component Architecture: Uses a component-based approach for form elements
- Validation System: Flexible validation with custom error messages
- List Management: Special handling for arrays of form items
- Transformations: Support for transforming data between the view and the model
- History Management: A dedicated hook
useFormHistorylistens for form changes and manages a history stack for undo/redo operations.
🧪 Running Tests
yarn test📝 License
MIT © Felipe Rohde
👨💻 Author
Felipe Rohde
- Twitter: @felipe_rohde
- Github: @feliperohdee
- Email: [email protected]
