React Hooks 도입 후 Form 상태 관리 개선기
배경
회원가입 폼이 점점 복잡해지면서 Class 컴포넌트의 this.setState와 lifecycle 메서드가 난잡해졌다. React 16.8이 정식 릴리즈되고 몇 달 지났으니 Hooks를 실무에 적용해보기로 했다.
기존 코드의 문제
class SignupForm extends Component {
state = {
email: '',
password: '',
errors: {}
}
handleChange = (e) => {
this.setState({ [e.target.name]: e.target.value })
}
componentDidUpdate(prevProps, prevState) {
if (prevState.email !== this.state.email) {
this.validateEmail()
}
}
// ...
}
유효성 검증 로직이 여러 lifecycle에 흩어져 있고, 비슷한 Form을 만들 때마다 코드를 복사했다.
Hooks로 개선
커스텀 Hook으로 Form 로직을 분리했다.
function useForm(initialValues, validate) {
const [values, setValues] = useState(initialValues)
const [errors, setErrors] = useState({})
const handleChange = (e) => {
const { name, value } = e.target
setValues(prev => ({ ...prev, [name]: value }))
}
useEffect(() => {
const validationErrors = validate(values)
setErrors(validationErrors)
}, [values])
return { values, errors, handleChange }
}
// 사용
function SignupForm() {
const { values, errors, handleChange } = useForm(
{ email: '', password: '' },
validateSignup
)
return (
<form>
<input name="email" value={values.email} onChange={handleChange} />
{errors.email && <span>{errors.email}</span>}
</form>
)
}
결과
- 3개 Form 컴포넌트에서
useForm재사용 - Class 컴포넌트 대비 코드 120줄 → 85줄
- 테스트 작성도 더 쉬워졌다
아직 팀 전체가 Hooks에 익숙하지 않아 러닝커브가 있지만, 점진적으로 확대 적용할 계획이다.