use-manage-form
v2.1.1
Published
A react hook used to manage form and form input states
Downloads
32
Maintainers
Readme
USE-MANAGE-FORM
The use-manage-form is a React hook used to manage form states in a component. As a React developer, many a time i've come across scenarios where i'll have to manage multiple states and validation logic because of a single form, that's what inspired me to develop this hook and publish it so I and developers like me can use them to make development easier.
Installation
Inorder to install this package, one should run npm install use-manage-form
OR yarn add use-manage-form
. To install a specific version run npm install use-manage-form@version
OR yarn add use-manage-form@version
. Replace version with the package version e.g 1.0.0.
How to use the package
To use the package/hook, you import it at the top of your .js
/.ts
file.
import { useInput, useForm } from "use-manage-form";
useInput hook
The useInput
hook is responsible for managing each input state, properties and validation. E.g:
const { value, isValid, inputIsInValid, onChange, onBlur, reset } =
useInput(validateFunction);
It returns an object containing the
value
of the inputisValid
boolean if the input is valid or not (based on the validateFunction)inputIsInValid
boolean if the input field is inValid or not (based on the validateFunction and if the input field has been touched)onChange
function to be executed inorder to change the value of the inputonBlur
function to be executed to indicate that the input has been touched (to set the inputIsInvalid value properly)reset
function to be executed to reset the value of the input and inputWasTouched to empty and false respectively
The useInput
hook also accepts a function validateFunction
as a parameter that should return the input validator. It passes the input value as a parameter to the function validateFunction
. E.g:
useInput((/**@type String*/ value) => {
return value.trim() !== "";
});
Inorder to update the input value you should pass the onChange
function from useInput
hook to the input's onChange
prop. I.e:
<input
type="text"
onChange={(/**@type Event */ e) => {
onChange(e.target?.value);
}}
id="name"
/>
To perform two way binding, you also need to pass the value
property from the useInput
hook to the input's value
prop. I.e:
<input
type="text"
onChange={(/**@type Event */ e) => {
onChange(e.target?.value);
}}
id="name"
value={value}
/>
To indicate that the input was touched you'll need to pass the onBlur
function from the useInput
hook to the input's onBlur
prop. I.e:
<input
type="text"
onChange={(/**@type Event */ e) => {
onChange(e.target?.value);
}}
onBlur={() => {
onBlur();
}}
id="name"
value={value}
/>
To reset an input, just call the reset
function. E.g:
reset();
You can use the inputIsInValid
property to show some error if the input field is invalid. The difference between the isValid
and inputIsInValid
properties are
isValid
returnstrue
orfalse
based on thevalidateFunction
passed into theuseInput
hook.inputIsInValid
returnstrue
orfalse
based on both theisValid
andinputWasTouched
properties.inputIsInValid
is used for error stylings. I.e: The input is always invalid because it's empty at first, therefore, theisValid
prop returnsfalse
. If you use theisValid
prop to determine the error styling (Display input error message), it will be displayed when the page is loaded, But if theinputIsInValid
prop is used - the error would only be displayed if the user has touched the input or has clicked the submit button. E.g:
<div>
<input
type="text"
onChange={(/**@type Event */ e) => {
onChange(e.target?.value);
}}
onBlur={() => {
onBlur();
}}
value={value}
id="name"
/>
{inputIsInValid && <p className="error-text">Name must not be empty.</p>}
</div>
You can rename each property in case you are using multiple useInput
. E.g:
const {
value: firstName,
isValid: firstNameIsValid,
inputIsInValid: firstNameInputIsInValid,
onChange: firstNameChangeHandler,
onBlur: firstNameBlurHandler,
reset: resetFirstName,
} = useInput((value) => value.trim() !== "");
useForm hook
The useForm
hook is used to manage the states of a whole form, it manages the formIsValid state and other functions.
The useForm
hook returns three properties namely:
{
executeBlurHandlers,
formIsValid,
reset,
}
- The
executeBlurHandlers
executes all form inputonBlur
functions passed to theuseForm
hook. - The
formIsValid
returnstrue
/false
, based on the function passed to the useFormhook
. - The
reset
resets all form inputs passed to theuseForm
hook.
The useForm
hook accepts an object containing:
blurHandlers
: The list of all inputonBlur
functions to be executed (to be executed when form is submitted, but NOT validated, it sets theinputWasTouched
value of all inputs passed into it totrue
andinputIsInValid
states to true for invalid inputs).validateOptions
: ThevalidateFunction
used to determine if the form is valid or notresetHandlers
: The list of all inputreset
functions (To reset all input values andinputWasTouched
values to empty and false respectively)
Therefore, the useForm
is to be called this way:
const { executeBlurHandlers, formIsValid, reset } = useForm({
blurHandlers: [firstNameBlurHandler, lastNameBlurHandler, emailBlurHandler],
validateOptions: () => firstNameIsValid && lastNameIsValid && emailIsValid,
resetHandlers: [resetFirstName, resetLastName, resetEmail],
});
The onSubmit
function passed to the form could be then implemented this way:
const onSubmit = (/**@type Event*/ e) => {
e.preventDefault();
if (!formIsValid) {
executeBlurHandlers();
return false;
}
};
...
return(
<form onSubmit={onSubmit}>
</form>
)
At the end our code base should be similar to this
import { useForm, useInput } from "use-manage-form";
const BasicForm = (props) => {
const {
value: firstName,
isValid: firstNameIsValid,
inputIsInValid: firstNameInputIsInValid,
onChange: firstNameChangeHandler,
onBlur: firstNameBlurHandler,
reset: resetFirstName,
} = useInput((value) => value.trim() !== "");
const {
value: lastName,
isValid: lastNameIsValid,
inputIsInValid: lastNameInputIsInValid,
onChange: lastNameChangeHandler,
onBlur: lastNameBlurHandler,
reset: resetLastName,
} = useInput((value) => value.trim() !== "");
const {
value: email,
isValid: emailIsValid,
inputIsInValid: emailInputIsInValid,
onChange: emailChangeHandler,
onBlur: emailBlurHandler,
reset: resetEmail,
} = useInput((value) => value.trim() !== "" && value?.includes("@"));
const { executeBlurHandlers, formIsValid, reset } = useForm({
blurHandlers: [firstNameBlurHandler, lastNameBlurHandler, emailBlurHandler],
validateOptions: () => firstNameIsValid && lastNameIsValid && emailIsValid,
resetHandlers: [resetFirstName, resetLastName, resetEmail],
});
const firstNameInputClasses = firstNameInputIsInValid
? "form-control invalid"
: "form-control";
const lastNameInputClasses = lastNameInputIsInValid
? "form-control invalid"
: "form-control";
const emailInputClasses = emailInputIsInValid
? "form-control invalid"
: "form-control";
const onSubmit = (/**@type Event*/ e) => {
e.preventDefault();
if (!formIsValid) {
executeBlurHandlers();
return false;
}
console.log("SUBMIT", {
firstName,
lastName,
email,
});
reset();
};
return (
<form onSubmit={onSubmit}>
<div className="control-group">
<div className={firstNameInputClasses}>
<label htmlFor="name">First Name</label>
<input
type="text"
onChange={(/**@type Event */ e) => {
firstNameChangeHandler(e.target?.value);
}}
onBlur={() => {
firstNameBlurHandler();
}}
value={firstName}
id="name"
/>
{firstNameInputIsInValid && (
<p className="error-text">Firstame must not be empty.</p>
)}
</div>
<div className={lastNameInputClasses}>
<label htmlFor="name">Last Name</label>
<input
type="text"
id="name"
onChange={(/**@type Event */ e) => {
lastNameChangeHandler(e.target?.value);
}}
onBlur={() => {
lastNameBlurHandler();
}}
value={lastName}
/>
{lastNameInputIsInValid && (
<p className="error-text">Lastname must not be empty.</p>
)}
</div>
</div>
<div className={emailInputClasses}>
<label htmlFor="name">E-Mail Address</label>
<input
type="text"
id="name"
onChange={(/**@type Event */ e) => {
emailChangeHandler(e.target?.value);
}}
onBlur={() => {
emailBlurHandler();
}}
value={email}
/>
{emailInputIsInValid && (
<p className="error-text">
Email must not be empty and must be a valid email.
</p>
)}
</div>
<div className="form-actions">
<button disabled={!formIsValid}>Submit</button>
</div>
</form>
);
};
export default BasicForm;
Thank you, if this helped you i would appreciate you star the repo Use-manage-form repo