리액트에서 폼을 다룰 때, 주로 두 가지 방법이 사용되는데, 제어 컴포넌트와 비제어 컴포넌트이다.
리액트에서 폼 요소를 제어 컴포넌트로 만들면 값이 리액트의 상태에 의해 제어된다. 이렇게 하면 값의 변경을 감지하고 다루기가 훨씬 수월하다.
폼 요소의 상태는 컴포넌트의 state에 저장되고, 사용자가 입력을 변경할 때마다 상태를 업데이트하는 방식이다.
import React, { useState } from 'react';
function ControlledForm() {
const [formData, setFormData] = useState({
username: '',
email: '',
password: ''
});
const handleChange = (e) => {
const { name, value } = e.target;
setFormData({
...formData,
[name]: value
});
};
const handleSubmit = (e) => {
e.preventDefault();
console.log('Form submitted:', formData);
};
return (
<form onSubmit={handleSubmit}>
<div>
<label>
Username:
<input
type="text"
name="username"
value={formData.username}
onChange={handleChange}
/>
</label>
</div>
<div>
<label>
Email:
<input
type="email"
name="email"
value={formData.email}
onChange={handleChange}
/>
</label>
</div>
<div>
<label>
Password:
<input
type="password"
name="password"
value={formData.password}
onChange={handleChange}
/>
</label>
</div>
<button type="submit">Submit</button>
</form>
);
}
export default ControlledForm;
비제어 컴포넌트는 리액트 컴포넌트가 폼의 상태를 관리하지 않고, 폼 입력을 DOM 자체에서 처리한다.
비제어 컴포넌트는 ref를 사용해 폼 요소에 직접 접근할수 있다. 때문에, 리액트의 상태를 사용하지 않고 폼 요소의 값을 직접 읽을 수 있다.
리액트에서는 useRef와 createRef라는 두 가지 방법으로 ref를 만들 수 있다. 함수형 컴포넌트에서는 useRef를, 클래스 컴포넌트에서는 createRef를 사용한다.
import React, { useRef } from 'react';
function UncontrolledForm() {
const usernameRef = useRef();
const emailRef = useRef();
const passwordRef = useRef();
const handleSubmit = (e) => {
e.preventDefault();
const formData = {
username: usernameRef.current.value,
email: emailRef.current.value,
password: passwordRef.current.value
};
console.log('Form submitted:', formData);
};
return (
<form onSubmit={handleSubmit}>
<div>
<label>
Username:
<input
type="text"
ref={usernameRef}
/>
</label>
</div>
<div>
<label>
Email:
<input
type="email"
ref={emailRef}
/>
</label>
</div>
<div>
<label>
Password:
<input
type="password"
ref={passwordRef}
/>
</label>
</div>
<button type="submit">Submit</button>
</form>
);
}
export default UncontrolledForm;
상태에 따른 로직을 쉽게 구현할 수 있고, 상태를 중앙에서 관리할 수 있다.
코드가 다소 복잡해질 수 있다.
코드가 간결하고 단순하고, 리액트의 상태 관리 없이도 폼 값을 관리할 수 있다.
상태에 따른 로직을 구현하기 어렵다.