Form, 제어 컴포넌트와 비제어 컴포넌트

Ryan Cho·2024년 11월 22일
0

프론트엔드 개발에서 form관리는 매우 중요하고 복잡한 작업이다.
현재 리액트 생테계에서 가장 각광받는 form관련 툴은 react-hook-form이다.
이를 제대로 활용하기 위해서는 먼저 HTML의 기본태그인 form에 대해 이해해보자.

form의 필수 요소

라벨,인풋의 속성 등 필수적인건 더 있지만 내가 강조하고 싶은 부분은 버튼이다
폼 내부의 버튼은 타입에 따라 다르게 작동한다. 기획자가 Submit버튼만 제시하더라도 늘 Reset버튼을 염두해두고 개발을 진행하는걸 추천한다. 결국엔 필요해질 가능성이 매우 높다

<form onSubmit={} id='' method=''>
	<input />
    <button type='submit'>Submit</button>
    <button type='reset'>Reset</button>
</form>

React에서 form을 관리하는 방식은 비제어 방식제어 방식으로 나뉜다.

비제어 방식

이는 가장 기본적인 form관리의 방식인데, DOM기반으로 관리하는 방식이다.
제어 방식과 달리 입력값 변경시마다 리렌더링이 발생하지 않고 성능적인 면에 이점이 있을 수 있다.

function UnControlledComponent() {

  const onSubmit: FormEventHandler<HTMLFormElement> = (e) => {
    e.preventDefault(); // 기본동작(폼 제출 막는 용도, SPA목적)
    const formData = new FormData(e.currentTarget);
    alert(JSON.stringify(Object.fromEntries(formData.entries())));
  };

  return (
    <form onSubmit={onSubmit} id="form" method="post">
      <input name="id" defaultValue='id'/> // 제어방식에서는 defaultValue불가
      <input name="password"/>
      <button type="submit">Submit</button>
      <button type="reset">Reset</button>
    </form>
  );
}

제어 방식

이는 폼 입력값이 React state에 의해 제어되는 방식이다. 입력값이 변화할때마다 state를 업데이트하는 방식이고 매번 리렌더링을 유발시킨다.
하지만 모든 데이터가 React 컴포넌트 내에서 관리되어 데이터 흐름이 명확하다는 장점이 있다.

function ControlledComponent() {
  const onSubmit: FormEventHandler<HTMLFormElement> = (e) => {
    e.preventDefault()
    const formData = new FormData(e.currentTarget)
    alert(JSON.stringify(Object.fromEntries(formData.entries())))
  }
  const [id, setId] = useState('')
  const [password, setPassword] = useState('')

  return (
    <form onSubmit={onSubmit} id="form" method="post">
      <input name="id" value={id} onInput={(e) => { setId(e.currentTarget.value) }} />
      <input name="password" value={password} onInput={(e) => { setPassword(e.currentTarget.value) }} />
      <button type="submit">Submit</button>
      <button type="reset">Reset</button>
    </form>
  )
}
profile
From frontend to fullstack

0개의 댓글