오늘은 form을 만드는 두 가지 방법에 대해 알아보았다.
Controlled Component: 제어 컴포넌트
Uncontrolled Component: 비제어 컴포넌트
사용자가 무언가를 클릭하거나 했을 때 UI가 업데이트 되어야 한다면, React Component 자체 내 상태가 변경되면서 UI가 업데이트 되어야 하는데,
import React, { useState } from "react";
export default function AppForm() {
const handleSubmit = (e) => {
e.preventDefault();
console.log(form);
};
return (
<form onSubmit={handleSubmit}>
<label htmlFor="name">이름:</label>
<input
type="text"
id="name"
name="name"
/>
<label htmlFor="email">이메일:</label>
<input
type="email"
id="email"
name="email"
/>
<button>Submit</button>
</form>
);
}
이렇게 만든 form을 보면 input에 입력을 했을 때 React 내부적으로 상태 변경이 이루어지지 않아도 바로 UI상에서 내가 입력한 것이 보인다.
이런 것을 Uncontrolled Component라고 한다.
이런 경우 React가 추구하는 원칙과 어긋나기 때문에 데이터가 보여질 때 이 컴포넌트에서 가지고 있는 상태와 똑같이 매칭이 되도록 만들어주어야 한다!
이 말인즉슨 Controlled Component로 만들어 줘야 한다는 의미!
그렇게 하려면 무엇을 이용한다? 바로 useState
!
import React, { useState } from "react";
export default function AppForm() {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
};
return (
<form onSubmit={handleSubmit}>
<label htmlFor="name">이름:</label>
<input
type="text"
id="name"
name="name"
value={name}
onChange={(e) => {
setName(e.target.value);
}}
/>
<label htmlFor="email">이메일:</label>
<input
type="email"
id="email"
name="email"
value={email}
onChange={(e) => {
setEmail(e.target.value);
}}
/>
<button>Submit</button>
</form>
);
}
이렇게 작성하면
이렇게 input에 작성할 때마다 상태가 업데이트 되는 걸 확인할 수 있다.
그런데 여기서!!
이름과 이메일은 사용자에 관한 정보이므로 하나의 객체로 묶어서 상태를 관리해 주면 어떨까?
import React, { useState } from "react";
export default function AppForm() {
const [form, setForm] = useState({ name: "", email: "" });
const handleSubmit = (e) => {
e.preventDefault();
};
const handleChange = (e) => {
const { name, value } = e.target;
setForm({ ...form, [name]: value });
};
return (
<form onSubmit={handleSubmit}>
<label htmlFor="name">이름:</label>
<input
type="text"
id="name"
name="name"
value={form.name}
onChange={handleChange}
/>
<label htmlFor="email">이메일:</label>
<input
type="email"
id="email"
name="email"
value={form.email}
onChange={handleChange}
/>
<button>Submit</button>
</form>
);
}
handleChange
라는 함수를 따로 만들어서 onChange
에 걸어줬는데, 이벤트에서 발생하는 target의 name과 value를 받아와서 setForm을 해주는 것이다!
그런데 여기서,
setForm({ ...form, [name]: value });
왜 name을 대괄호로 감싸주는 것인지 궁금해서 찾아보았더니,
객체의 key값이 동적으로 할당될 때는 []형식으로 써주어야 한다고 한다!
++ form에서 submit 버튼을 클릭했을 때 페이지가 refresh 되는 걸 원치 않는다면 꼭 preventDefault
함수를 실행시켜야 한다!!