제어 컴포넌트와 비제어 컴포넌트
제어 컴포넌트와 비제어 컴포넌트란, React에서 form 태그 엘리먼트를 다루는 방법이다. form 태그 엘리먼트는 자체적으로 데이터를 가진다는 특정이 있다. 이 특성 때문에 form 태그 엘리먼트를 다루는 방법이 두 가지로 나뉜다. form 태그 엘리먼트 중 가장 자주 사용되는 input 태그를 예로 들어 제어 컴포넌트와 비제어 컴포넌트를 설명해보려 한다.
React에서는 input의 value 값을 다룰 때 state를 사용하거나 ref를 사용한다. state를 사용하는 것을 제어 컴포넌트, ref를 사용하는 것을 비제어 컴포넌트라고 한다.
# 제어 컴포넌트
import React, { useState } from 'react';
export default function App() {
const [email, setEmail] = useState();
const handleChange = (event) => {
setPassword(event.target.value);
};
return (
<div>
<input
type="text"
value={email}
onChange={handleChange}
/>
</div>
);
}
useState로 input의 value를 저장하고, input의 입력값이 변경될 때마다 useState는 값을 업데이트한다. 값이 바뀔 때마다 리렌더링이 일어나기 때문에 화면에 보이는 값과 컴포넌트가 관리하는 상태의 값이 일치한다.
# 비제어 컴포넌트
비제어 컴포넌트란 input의 데이터를 DOM 자체에 저장하는 것으로, ref를 이용하여 직접 input의 데이터에 접근하는 것이다. 이 모습은 바닐라 자바스크립트와 상당히 비슷하다. 우선 바닐라 자바스크립트를 살펴보자.
<!-- 바닐라 자바스크립트 -->
<body>
<script>
const inputChange = () => {
const test = document.getElementById("test");
document.getElementById("result").innerText = test.value;
};
</script>
<input id="test" onchange="inputChange()" />
<h1 id="result"></h1>
</body>
바닐라 자바스크립트에서는 getElementbyId를 이용해 직접 값에 접근한다. 이와 마찬가지로 React에서는 DOM에 접근하여 input 값에 접근하고 싶다면 ref를 이용한다.
import React, { useRef } from 'react';
export default function App() {
const inputRef = useRef();
const handleClick = () => {
console.log(inputRef.current.value);
}
return (
<div>
<input ref={inputRef} />
<button onClick={handleClick}>확인</button>
</div>
);
}
이 방법을 이용하면 값이 실시간으로 동기화되지 않는다. 제어 컴포넌트는 사용자가 입력을 할 때마다 리렌더링을 시키고 값을 동기화하는 반면 비제어 컴포넌트는 사용자가 직접 동작을 하기 전까지는 리렌더링을 하지 않고 값을 동기화하지도 않는다.
제어 컴포넌트를 사용하면 값을 실시간으로 확인할 수 있지만 계속해서 리렌더링이 되기 때문에, 불필요한 리렌더링을 줄이고 제출 시에만 값을 사용하고자 한다면 비제어 컴포넌트를 사용하는 것이 좋다.
input 다룰 때 항상 state만 써봤는데 ref를 쓰는 방법이 있었구나😮 로그인 기능 구현할 때 글자 하나하나 다 리렌더 되는 게 비효율적이라 바꾸고 싶었는데 ref를 써봐야겠다
참고 자료
[10분 테코톡] 후이의 제어 컴포넌트 vs 비제어 컴포넌트 https://youtu.be/LD1LyvCCbCg
'FE - Tools > React' 카테고리의 다른 글
[React] Context API와 useReducer 사용법 알아보기 (0) | 2023.05.11 |
---|---|
[React] Express로 CORS 에러 해결하기 (0) | 2023.03.01 |
[React] React에서 네이버 지도 API 사용하기 (0) | 2023.01.19 |
[React] useParams 이용하기 (0) | 2022.12.22 |
[React] useEffect와 useLayoutEffect의 차이 (0) | 2022.12.20 |