자 우선 React에서 useRef
hook을 어떻게 사용하는 지 살펴봅시다.
import { useRef } from 'react';
const ref = useRef(0);
리액트 컴포넌트 내에서 useRef
hook을 사용해 초기값 0
을 넘겨주었습니다.
위 예시에서, useRef
는 다음과 같은 객체를 return합니다.
{
current: 0 // The value you passed to useRef
}
이제 ref.current
속성을 통해 해당 참조의 현재 값에 접근할 수 있습니다. 이 값은 의도적으로 변경 가능하므로(mutable) 읽고 쓸 수 있습니다.
마치 리액트가 추적하지 않는 ‘비밀 주머니’라고 생각해보세요.
(이것이 React의 단반향 데이터 흐름에서 마치 ‘탈출구(escape hatch)'의 역할을 하는 것입니다.)
import { useRef } from 'React';
export default function Counter() {
let ref = useRef(0);
function handleClick() {
ref.current = ref.current + 1;
alert('You Clicked ' + ref.crruent + ' times!');
}
return (
<button onClick={handleClick}>
Click me!
</button>
)
}
ref는 숫자를 가리키지만, state
처럼 문자열, 객체 또는 함수 등 무엇이든 가리킬 수 있습니다. state
와 달리 ref
는 current
라는 읽고 수정할 수 있는 속성이 있는 일반 JavaScript 객체입니다.
여기서 알아두어야 할 점은, ’컴포넌트는 ref가 증가할 때마다 리렌더링되지 않는다’는 점입니다. state
와 마찬가지로 ref
는 리렌더링 사이에 값이 유지됩니다. 그러나, state
는 변경하면 컴포넌트를 리렌더링 시킵니다. ref
를 변경하는 것은 컴포넌트를 렌더링 시키지 않습니다.
state
는 값을 변경하면 해당 컴포넌트가 렌더링된다. 하지만ref
는 값을 변경한다해도 컴포넌트가 렌더링되지 않는다.
그러므로 코드를 짤 때에, 해당 정보가 렌더링이 필요한 값이면 state
를 써주는 것이 좋습니다.
또한, 해당 정보가 이벤트 핸들러에서만 필요하고 정보 변경 시 다시 렌더링할 필요가 없는 경우에는 ref
를 사용하는 것이 더 효율적입니다.
아마도 refs
를 사용하는 것이 state
를 사용하는 것보다 덜 ‘엄격’하다고 생각 할 수 있습니다. - 항상 함수를 사용하지 않고 값을 변경할 수 있기때문에
하지만 대부분의 경우, state
를 사용하는 것이 좋습니다.
Refs
는 자주 필요하지 않는 '탈출구'라고 생각하면 이해하기 조금 더 쉬울 것입니다.
refs | state |
---|---|
useRef(initialValue) return { current: initialValue } | useState(initialValue) returns the current Value of a state variable and a state setter function ([value, setValue] ) |
변경해도 다시 렌더링하지 않는다. | 변경하면 렌더링한다. |
변경 가능 - 렌더링 과정의 바깥에서 current 의 값을 변경하고 업데이트할 수 있다. | 불변 - state를 설정하는 함수를 사용하여 상태 변수를 수정해 렌더링 대기열에 넣어야 한다. |
current 렌더링 중에 값을 읽거나 쓰지 않아야 한다. | 언제든지 상태를 읽을 수 있다. 그러나 각 렌더링에는 변경되지 않는 자체 snapshot 상태가 있다. |
일반적으로는, 컴포넌트가 리액트의 ‘외부로 나가‘ 외부 API(컴포넌트의 모양에 영향을 주지 않는 브라우저 API)와 통신해야 할 때 ref를 사용합니다.
컴포넌트가 어떤 값을 저장할 필요가 있지만, 렌더링 로직에 영향을 주지 않는다면, refs를 사용하는 것이 좋습니다.
React는 렌더링 출력과 동일하도록 DOM을 자동으로 업데이트하므로 컴포넌트가 자주 DOM을 조작할 필요가 없습니다. 그러나 경우에 따라 React에서 관리하는 DOM 요소에 접근해야 할 수도 있습니다. React에는 이러한 작업을 수행하는 기본 제공 방법이 없으므로 이때, ref
를 사용해 DOM 노드에 접근합니다.
다음 예시를 함께 봅시다.
const myRef = useRef(null)
<div ref={myRef}></div>
useRef
hook은 current
라 불리는 단일 속성을 가진 객체를 반환합니다.
처음에는 myRef.current
는 null
입니다. React가 이에 대한 DOM 노드를 생성하면 React <div>
는 이 노드에 대한 참조를 myRef.current
안에 넣습니다.
그럼 이벤트 핸들러에서 이 DOM 노드에 접근하고 여기에 정의된 내장 브라우저 API를 사용할 수 있습니다.
// You can use any brower APIs, for example:
myRef.current.scrollIntoView();
import { useRef } from 'react';
export default function Form() {
const inputRef = useRef(null);
function handleClick() {
inputRef.current.focus();
}
return (
<>
<input ref={inputRef} />
<button onClick={handleClick}>
Focus the input
</button>
</>
);
}
DOM 조작은 refs
를 사용하는 가장 일반적인 사례인데, useRef
hook은 React 외부의 다른 것들을 저장하는 데 사용할 수 있습니다.(timer ID와 같은) state
와 유사하게 ref
는 렌더링 사이에 값이 유지됩니다.