Lets say we have following form:
const UserSignup = () => {
const [userName, setUserName] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [passwordConfirmation, setPasswordConfirmation] = useState('');
const [investmentInterest, setInvestmentInterest] = useState(false);
const handleSubmit = event => {
event.preventDefault();
clear();
};
const clear = () => {
setUserName('');
setEmail('');
setPassword('');
setPasswordConfirmation('');
setInvestmentInterest(false);
};
return (
<form className="UserSignup" onSubmit={handleSubmit}>
<label htmlFor="userName">User Name</label>
<input
id="userName"
name="userName"
type="text"
value={userName}
required
onChange={event => {
setUserName(event.target.value);
}}
/>
<label htmlFor="email">Email Address</label>
<input
id="email"
name="email"
type="email"
value={email}
required
onChange={event => {
setEmail(event.target.value);
}}
/>
<label htmlFor="password">Password</label>
<input
id="password"
name="password"
type="password"
value={password}
required
onChange={event => {
setPassword(event.target.value);
}}
/>
<label htmlFor="passwordConfirmation">Confirm Password</label>
<input
id="passwordConfirmation"
name="passwordConfirmation"
type="password"
value={passwordConfirmation}
required
onChange={event => {
setPasswordConfirmation(event.target.value);
}}
/>
<label htmlFor="investmentInterest" className="UserSignup--checkbox">
<input
id="investmentInterest"
name="investmentInterest"
type="checkbox"
checked={investmentInterest}
onChange={event => setInvestmentInterest(event.target.checked)}
/>
Do you want to maybe help us out with an angel investment?
</label>
<input type="Submit" />
</form>
);
};
export default UserSignup;
We are using multiple setState to mantain state of the form fields can we simplify this? yes we can :).
Lets create a new file named useSetState.js
with following contents:
import { useReducer } from 'react';
const reducer = (previousState = {}, updatedState = {}) => {
return { ...previousState, ...updatedState };
};
const useSetState = (initialState = {}) => {
const [state, dispatch] = useReducer(reducer, initialState);
const setState = updatedState => dispatch(updatedState);
return [state, setState];
};
export default useSetState;
We are creating a reducer function which takes two objects and merges them together, if there are common fields the updateState
overwrites the previousState
.
Then we are creating a hook name useSetState
in recieves initialState
which by default is empty object.
We use the react’s provided useReducer
hook and pass a reducer to it which we created in the last step.
We create a function named setState
this function calls the dispatch of useReducer
with the updatedState
as a param.
Now we can update our UserSignup as follow:
import React, { useState } from 'react';
import useSetState from './useSetState';
import './UserSignup.css';
const initialState = {
userName: '',
email: '',
password: '',
passwordConfirmation: ''
};
const UserSignup = () => {
const [state, setState] = useSetState(initialState);
const handleChange = event => {
setState({
[event.target.name]: event.target.value
});
};
const handleSubmit = event => {
event.preventDefault();
clear();
};
const clear = () => {
setState(initialState);
};
return (
<form className="UserSignup" onSubmit={handleSubmit}>
<label htmlFor="userName">User Name</label>
<input
id="userName"
name="userName"
type="text"
value={state.userName}
required
onChange={handleChange}
/>
<label htmlFor="email">Email Address</label>
<input
id="email"
name="email"
type="email"
value={state.email}
required
onChange={handleChange}
/>
<label htmlFor="password">Password</label>
<input
id="password"
name="password"
type="password"
value={state.password}
required
onChange={handleChange}
/>
<label htmlFor="passwordConfirmation">Confirm Password</label>
<input
id="passwordConfirmation"
name="passwordConfirmation"
type="password"
value={state.passwordConfirmation}
required
onChange={handleChange}
/>
<input type="Submit" />
</form>
);
};
export default UserSignup;
This simplified and easy to read then the previous approach. This article was inspired from here