프로젝트를 진행 중에 component 안에서 toggle, step 등을 useState 말고 useRef를 사용하면 어떨까하는 생각을 갖게 되어서 그 차이점을 정리해보았다.
useRef는 re-rendering을 불러오지 않고, useState는 re-rendering을 불러일으킨다.
form에서 useRef를 사용하는 것은 Uncontrolled components
라고 칭한다. 이는 좀 더 'vanilla'스러운 방법인데 코드를 통해 보면 다음과 같다.
import React, {useRef} from 'react';
export const Uncontrolled = props => {
const inputRef = useRef(null);
const handleSubmit = event => {
event.preventDefault();
const $inputDOMNode = inputRef.current;
if ($inputDOMNode && $inputDOMNode.value) {
props.handleSubmittedData({ uncontrolled: $inputDOMNode.value });
}
};
return (
<form onSubmit={handleSubmit}>
<h2>Uncontrolled</h2>
<input
name="uncontrolled"
placeholder="uncontrolled"
type="text"
ref={inputRef}
/>
<button type="submit">Submit</button>
</form>
);
};
// source : https://able.bio/drenther/react-hook-form-handling-basics-uncontrolled-and-controlled-components--78e30mz
이 방법을 통해서는 해당 컴포넌트에 state가 없다. useRef를 통해 우리가 작성한 input을 가져와서 그 안에 담긴 value를 사용하는 식이다.
import React, { useState } from "react";
export const Controlled = props => {
const [controlledValue, updateControlledValue] = useState("");
const handleChange = event => {
updateControlledValue(event.target.value);
};
const handleSubmit = event => {
event.preventDefault();
props.handleSubmittedData({
controlled: controlledValue
});
};
return (
<form onSubmit={handleSubmit}>
<h2>Controlled</h2>
<input
name="controlled"
placeholder="controlled"
type="text"
value={controlledValue}
onChange={handleChange}
/>
<button disabled={!controlledValue} type="submit">
Submit
</button>
</form>
);
};
// source : https://able.bio/drenther/react-hook-form-handling-basics-uncontrolled-and-controlled-components--78e30mz
useState를 사용하게 되면 위와 같이 해당 컴포넌트 안에서 다룰 수 있는 state가 생성되게 된다. useRef를 사용하는 것보다 더 'react'스러운 행위라고 볼 수 있다.
위 링크에서 useRef와 useState를 비교해놓은 표를 확인할 수 있다.
useRef는 실시간성을 보장할 수 없고, useState를 사용해서 re-rendering되는 이슈는 useMemo 등을 통해 해결할 수 있다고 보고 있다.
결과적으로 form에서는 useState를 사용하는 것이 더 바람직하다고 볼 수 있다.
useForm의 register를 보면 알겠지만 useRef를 사용중이다. (사실 공식문서에도 나와있다) uncontrolled component이기에 re-rendering 양도 줄고, 컴포넌트 mount 속도도 더 빠르다고 한다.
물론 Controller는 material UI 등을 커버하기 위해서 controlled component를 위한 wrapper 역할을 해준다.
useState는 rendering이 필요할 때, useRef는 rendering이 필요없는 경우에 사용하자!
추가로 useRef는 react내의 특정 html 요소를 찝어내는 데에도 사용할 수 있다.