JAVASCRIPT
Create a Custom Hook for Form Input Management
Learn to build a reusable custom React hook for handling form input state, validation, and change events, simplifying form development.
import React, { useState } from 'react';
// Custom Hook for input management
function useInput(initialValue, validator) {
const [value, setValue] = useState(initialValue);
const [error, setError] = useState(null);
const handleChange = (event) => {
const newValue = event.target.value;
setValue(newValue);
if (validator) {
const validationError = validator(newValue);
setError(validationError);
}
};
const reset = () => {
setValue(initialValue);
setError(null);
};
return {
value,
error,
handleChange,
reset,
bind: {
value,
onChange: handleChange,
},
};
}
function MyForm() {
const nameValidator = (name) => (name.length < 3 ? 'Name must be at least 3 characters' : null);
const emailValidator = (email) => (!email.includes('@') ? 'Invalid email format' : null);
const nameInput = useInput('', nameValidator);
const emailInput = useInput('', emailValidator);
const handleSubmit = (event) => {
event.preventDefault();
if (!nameInput.error && !emailInput.error && nameInput.value && emailInput.value) {
alert(`Submitted: Name - ${nameInput.value}, Email - ${emailInput.value}`);
nameInput.reset();
emailInput.reset();
} else {
alert('Please fix the errors in the form.');
}
};
return (
<form onSubmit={handleSubmit}>
<div>
<label>Name:</label>
<input type="text" {...nameInput.bind} />
{nameInput.error && <p style={{ color: 'red' }}>{nameInput.error}</p>}
</div>
<div>
<label>Email:</label>
<input type="email" {...emailInput.bind} />
{emailInput.error && <p style={{ color: 'red' }}>{emailInput.error}</p>}
</div>
<button type="submit">Submit</button>
</form>
);
}
export default MyForm;
How it works: This custom hook, `useInput`, encapsulates the logic for managing a single form input's state, its change handler, and basic validation. It takes an `initialValue` and an optional `validator` function. It returns the current `value`, any `error` message, a `handleChange` function, a `reset` function, and a `bind` object (which conveniently provides `value` and `onChange` props for direct spreading onto an `<input />` element). This allows for cleaner, more reusable form input management across multiple components.