프론트엔드에는 여러 중요한 요소가 있지만 가장 중요하면서도 생각외로 까다로운게 form 태그의 사용이라고 생각한다.
단순히 form 태그를 작성하여 UI 를 꾸미는 것을 넘어 input 태그들의 값들을 관리하고 또 서버로 넘겨주는 동작을 해야하니 쉽지 않다.
그러니 form 태그를 사용하는 방법에 대해 공부해보겠다.
가장 기본적인 input 태그의 속성들에 대한 것이기 보단 데이터를 서버와 주고 받기 위한 방법을 공부해보겠다.
아래의 form 을 만들어서 작성해본다.


위 타입의 input 들은 간단하게 값을 보관할 수 있다.

<label className = 'test__label'>
이름
<input className = 'test__input__text' type = "text" name = "name" value = {formValue.name} onChange={handleInputValue}/>
</label>
<label className = 'test__label'>
생년월일
<input type = "date" name = "birth" className = 'test__input__date' value = {formValue.birth} onChange={handleInputValue}/>
</label>
<div className='flex gap-3'>
<label className='flex gap-3'>
<input type = "radio" name = "gender" value = "남성" onChange = {handleInputValue} />
남성
</label>
<label className='flex gap-3'>
<input type = "radio" name = "gender" value = "여성" onChange = {handleInputValue} />
여성
</label>
</div>
만약 위처럼 label 태그로 input 을 감싸지 않는다면 아래처럼 작성해야 한다.
<input id = "text_input" type = "text" />
<label htmlfor = "text_input">이름</label>
이렇게 작성해야 label 부분을 클릭해도 해당 id의 input 을 클릭한 것처럼 포커스가 간다.
위의 input 들은 아래처럼 onChange 함수를 작성하면 된다.

photo 데이터의 경우는 input[type:file] 에서 e.target.files 를 가져와야 하기때문에 위처럼 작성했다. input[type:file] 에서는 e.target.value 를 사용하지 않는다.
만약 input[type:file] 이 없다면 그냥 e.target.value 만 사용하면 된다.
위 사진에서 e.preventDefault() 를 사용했는데 만약 이렇게 작성하게 되면
text 타입이나 date 타입 UI 는 문제가 없으나 라디오 버튼을 클릭해도 클릭 표시가 나오지 않기에 저 명령어를 삭제해야한다. 물론 setFormValue 는 잘 동작한다.
사실 가장 기본적인 방식이다.


체크박스는 여러개를 동시에 선택할 수 있기때문에 취급이 약간 다르다.
우선 input[type:checkbox] 에서 checked 속성을 e.target.checked 를 통해 가져온다.
input[type:checkbox] 태그가 체크되어있다면 checked 는 당연히 true 이다.
그래서 checked가 true 라면 setFormValue 에 넣어주고,
false라면 setFormValue 에서 제거한다.
체크박스가 여러개를 받기에 당연히 배열로 저장되니 배열을 잘 처리하자.

input[type:file]은 Change 이벤트도 있지만 드래깅(dragging) 도 가능하다.
위의 onDragOver 와 onDrop 이 그 예시이다.


위가 직접 지정해서 발생하는 ChangeEvent 이고, 아래가 드래그해서 발생하는 dragEvent 이다.
위에서 말했지만 input[type:file] 에서는 e.target.value를 사용할 수 없다. 이때는 .file 을 사용해야 하는데 두 방식에 따라 사용방식이 약간 다르다.

ChangeEvent 에서는 e.target.files 를 사용한다.

dragEvent 에서는 e.dataTransfer.files 를 사용한다.
이때 handleDragOver와 handleDrop 은 같이 다니는 형제이다.
그래서 handleDragOver에 e.preventDefault 를 해주지 않으면 onDrop 이 발생하지 않으며, onDrop 에 e.preventDefault 를 해주지 않으면 브라우저가 드롭한 파일을 연다.
위의 name에 빨간줄이 쳐있는데, currentTarget 이라고 작성하면 빨간줄이 사라지지만, 파일을 드래그 후에 추가적인 드래그 이벤트나, 체인지 이벤트가 발생하면 name 을 읽을 수 없다고 에러가 발생했다. 위처럼 작성하면 에러가 발생하지 않았다.
DragEvent 에는 onDragEnter, onDragLeave, onDragOver, onDrop 이 있다.



위처럼 new FormData() 로 데이터를 전송하면 쉽게 데이터를 제출할 수 있다.