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에 익숙하지 않아 러닝커브가 있지만, 점진적으로 확대 적용할 계획이다.

React Hooks 도입 후 Form 상태 관리 개선기