react-form
A context & hook based react form. Supports dirty-check, validation, reset and save functionalities of form
Features
-
Dirty Checking
- Dirty checks for both individual fields and whole form
- Marks current values as pristine on successful submit
- Single method tp reset the complete form to last known pristine values
-
Validation
- Supports writing your own custom validation rules
- Live validation at both individual field level and whole form level
- Does not check for required field errors until first submit
- Live validation for required fields after first submit
-
General
Installation
npm i --save @avcs/react-form
Documentation
useForm: ReactHook
arguments: [{
formData: { [string | symbol]: any };\
onFormChange?: (formMeta: { isFormDirty: boolean, formData: { [string | symbol]: any } }) => void;
onErrorChange?: (errorMeta: { hasErrors: boolean, errors: { [string | symbol]: any } }) => void;
}]
returnValue: {
handleSubmit: (
onSubmit: (formData: { [string | symbol]: any }) => any,
onError: (errors: { [string | symbol]: any }) => any
) => void;
clearForm: () => void;
FormProvider: React.Element
}
useFormContext: ReactHook
returnValue: {
}
useFormState<T>: ReactHook
arguments: [
key: string | symbol,
{
defaultValue?: any,
validate?: (value: any) => any | undefined,
required?: boolean,
requiredErrorMessage?: any,
provider?: React.Element
}
]
returnValue: [
state: T,
setState: ReactSetState<T>,
isDirty: boolean,
error: any,
]
Please note: error is any instead of string, this is there so you can pass anything.
Example: You can pass reference to the error node so you can scroll to specific error when clicking submit
Usage
Can be used in 2 different formats. Form & Fields in a single component or in separate components,
please refer below for an example of both the use cases
Form
import React from 'react';
import { useForm } from '@avcs/react-form';
const Form = () => {
const {
handleSubmit, clearForm, FormProvider
} = useForm({ formData: initialForm });
const [field, setField, isFieldDirty, fieldError] = useFormField(key, {
defaultValue: 'some value',
validate: (value) => {
if (value !== 'some value') return 'some error';
},
required: true,
requiredErrorMessage: 'this field is required',
provider: FormProvider
});
const handleChange = useCallback((e) => {
setData(e.target.value);
}, []);
const submitForm = useCallback((e) => {
handleSubmit(
formData => {
},
errors => {
}
);
}, []);
return (
<form>
{/* OPTION 1: using form fields separately,
see below for definition of FormField */}
<FormProvider>
<FormField />
</FormProvider>
{/* OPTION 2: using form field in same component as form */}
<input type="text" onChange={handleChange} value={field} />
<button onClick={submitForm}>Submit</input>
<button onClick={clearForm}>Clear</button>
</form>
);
};
export default Form;
FormField
import React from 'react';
import { useFormState } from '@avcs/react-form';
const FormField = () => {
const [data, setData, isDirty, error] = useFormState(key, {
defaultValue: 'some value',
validate: (value) => {
if (value !== 'some value') return 'some error';
},
required: true,
requiredErrorMessage: 'this field is required',
});
const handleChange = useCallback((e) => {
setData(e.target.value);
}, []);
return (
<input type="text" onChange={handleChange} value={data} />
);
};
export default FormField;
Performance
- useForm: re-renders once per load, submit, reset
- useFormContext: re-renders once per load
- useFormField: re-renders once per load, submit, reset, value-change
- onFormChange: triggers once per value-change
- oErrorChange: triggers once per error-change (adding a new error, clearing an error)