JAVASCRIPT
Managing Complex Form State with useReducer
Simplify complex form state logic in React by using the useReducer hook. Ideal for forms with multiple fields and intricate validation or submission flows.
import React, { useReducer } from 'react';
const initialFormState = {
username: '',
email: '',
password: '',
errors: {}
};
function formReducer(state, action) {
switch (action.type) {
case 'FIELD_CHANGE':
return {
...state,
[action.field]: action.value,
errors: { ...state.errors, [action.field]: undefined } // Clear error on change
};
case 'SET_ERRORS':
return {
...state,
errors: { ...state.errors, ...action.errors }
};
case 'RESET_FORM':
return initialFormState;
default:
return state;
}
}
function SignupForm() {
const [formState, dispatch] = useReducer(formReducer, initialFormState);
const { username, email, password, errors } = formState;
const handleChange = (e) => {
dispatch({
type: 'FIELD_CHANGE',
field: e.target.name,
value: e.target.value
});
};
const handleSubmit = (e) => {
e.preventDefault();
const newErrors = {};
if (!username) newErrors.username = 'Username is required.';
if (!email) newErrors.email = 'Email is required.';
if (!password || password.length < 6) newErrors.password = 'Password must be at least 6 characters.';
if (Object.keys(newErrors).length > 0) {
dispatch({ type: 'SET_ERRORS', errors: newErrors });
} else {
// Simulate API call
console.log('Form Submitted:', { username, email });
alert('Form Submitted Successfully!');
dispatch({ type: 'RESET_FORM' });
}
};
return (
<form onSubmit={handleSubmit} style={{ display: 'flex', flexDirection: 'column', gap: '10px', maxWidth: '300px', margin: '20px auto', padding: '20px', border: '1px solid #ccc', borderRadius: '8px' }}>
<div>
<label>
Username:
<input type="text" name="username" value={username} onChange={handleChange} />
</label>
{errors.username && <p style={{ color: 'red', fontSize: '0.8em' }}>{errors.username}</p>}
</div>
<div>
<label>
Email:
<input type="email" name="email" value={email} onChange={handleChange} />
</label>
{errors.email && <p style={{ color: 'red', fontSize: '0.8em' }}>{errors.email}</p>}
</div>
<div>
<label>
Password:
<input type="password" name="password" value={password} onChange={handleChange} />
</label>
{errors.password && <p style={{ color: 'red', fontSize: '0.8em' }}>{errors.password}</p>}
</div>
<button type="submit">Sign Up</button>
<button type="button" onClick={() => dispatch({ type: 'RESET_FORM' })}>Reset</button>
</form>
);
}
// To use, render <SignupForm /> in your App component.
How it works: This snippet demonstrates using the `useReducer` hook for managing the state of a complex form. `useReducer` is ideal when state logic involves multiple sub-values or when the next state depends on the previous one. The `formReducer` handles different actions (like `FIELD_CHANGE`, `SET_ERRORS`, `RESET_FORM`), providing a clear and centralized way to update the form state and associated errors, making the form component cleaner and more maintainable.