Published On

React hooks - useRef


useRef는 React의 훅(Hook) 중 하나로, 주로 DOM 엘리먼트에 직접 접근하거나 렌더링과 관련 없는 값을 저장할 때 사용됩니다.

useState와 달리, 값이 변경되어도 컴포넌트를 다시 렌더링하지 않는 특징이 있습니다.


useRef의 정의와 기본 문법

useRef는 값이 변경되더라도 컴포넌트를 다시 렌더링하지 않는 값을 유지하거나, DOM 엘리먼트에 직접 접근하는 데 사용됩니다.

import { useRef } from "react";

// 일반적으로 초기값으로 null을 사용합니다.
const ref = useRef(initialValue);

초기값으로 null을 사용하는 이유

  • DOM 엘리먼트가 렌더링되기 전까지 null로 초기화하여 안전하게 접근.
  • 초기 상태를 명시적으로 나타냄.
  • null은 값이 비어 있음을 표현하는 일반적인 관례.
  • React의 DOM 참조 방식과 일관성 유지.(표준 관례)

주요 예시

1. DOM 엘리먼트에 접근

React에서 DOM 엘리먼트에 직접 접근해야 할 때 useRef를 사용합니다.

버튼 클릭 시 ref.current가 어떻게 변하는지 콘솔 로그를 통해 확인해 보겠습니다.

import { useRef } from "react";

function FocusInput() {
  const inputRef = useRef(null);

  const handleFocus = () => {
    console.log("Before focus:", inputRef.current); // 현재 DOM 요소를 출력
    inputRef.current.focus();
    console.log("After focus:", inputRef.current); // focus 메서드 호출 후 출력
  };

  return (
    <div>
      <input ref={inputRef} type="text" placeholder="포커스를 받아요!" />
      <button onClick={handleFocus}>포커스</button>
    </div>
  );
}
  • 버튼 클릭 전: inputRef.currentinput 태그의 엘리먼트를 가리킵니다.

  • 버튼 클릭 후: DOM 요소의 focus 상태가 변경됩니다. (autofocus)

Before focus: <input type="text" placeholder="포커스를 받아요!">
After focus: <input type="text" placeholder="포커스를 받아요!" autofocus>

2. 렌더링과 관련 없는 값 관리

useRef는 값이 변경되더라도 렌더링을 트리거하지 않는 값을 관리할 때 유용합니다.

예를 들어, 폼 입력 중복 방지와 같은 실용적인 기능을 구현할 수 있습니다.

아래의 코드처럼 사용자가 동일한 값을 여러 번 제출하지 못하도록 막을 수 있습니다.

import { useRef, useState } from "react";

function PreventDuplicateSubmission() {
  const [inputValue, setInputValue] = useState("");
  const lastSubmittedValue = useRef(""); // 마지막 제출 값을 저장

  const handleSubmit = () => {
    if (inputValue === lastSubmittedValue.current) {
      alert("중복된 값은 제출할 수 없습니다.");
      return;
    }
    // 새로운 값 제출
    lastSubmittedValue.current = inputValue;
    console.log("제출된 값:", inputValue);
    setInputValue(""); // 입력 필드 초기화
  };

  return (
    <div>
      <input
        type="text"
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)}
        placeholder="값을 입력하세요"
      />
      <button onClick={handleSubmit}>제출</button>
      <p>마지막 제출 값: {lastSubmittedValue.current}</p>
    </div>
  );
}

이 코드에서 초기값을 null이 아닌 ""빈 문자열로 설정한 이유는

null인 경우 아래의 경우가 있을때, 코드가 길어질 수 있기 때문입니다.

if (inputValue === lastSubmittedValue.current) {
  alert("중복된 값은 제출할 수 없습니다.");
}

if (
  lastSubmittedValue.current === null ||
  inputValue === lastSubmittedValue.current
) {
  alert("중복된 값은 제출할 수 없습니다.");
}
  • renderCount는 렌더링 횟수를 저장하지만, 값이 변경되어도 컴포넌트를 다시 렌더링하지 않습니다.
  • useEffect를 통해 렌더링 횟수를 추적하고, 값을 증가시킵니다.

3. 값의 이전 상태 추적

useRef를 사용하여 컴포넌트의 이전 상태를 저장할 수 있습니다. 이는 값이 변경되었을 때 이전 값을 비교하거나 로그를 남기고 싶을 때 유용합니다.

import { useEffect, useRef, useState } from "react";

function PreviousValueTracker() {
  const [count, setCount] = useState(0);
  const prevCount = useRef(0);

  useEffect(() => {
    prevCount.current = count; // 이전 값을 저장
  }, [count]);

  return (
    <div>
      <p>현재 값: {count}</p>
      <p>이전 값: {prevCount.current}</p>
      <button onClick={() => setCount(count + 1)}>값 증가</button>
    </div>
  );
}
  • prevCount는 count의 이전 상태를 저장하며, 렌더링과 관계없이 유지됩니다.
  • useEffect는 count가 변경될 때마다 prevCount.current에 현재 값을 저장합니다.

useRef의 주요 특징

특징설명
렌더링 트리거 없음useRef로 관리되는 값이 변경되어도 컴포넌트는 다시 렌더링되지 않습니다. 반면, useState는 상태 변경 시 컴포넌트를 다시 렌더링합니다.
DOM 엘리먼트 접근ref 속성을 DOM 요소에 전달하면 해당 DOM 요소를 가리킬 수 있습니다. 이를 통해 포커스, 스크롤 위치 등 DOM 조작이 가능합니다.
값의 지속성컴포넌트가 언마운트되지 않는 한, useRef로 관리되는 값은 컴포넌트의 수명 동안 유지됩니다.

useRef와 useState의 차이점

특징useRefuseState
초기값 설정useRef(initialValue)useState(initialValue)
렌더링 트리거값을 변경해도 컴포넌트를 다시 렌더링하지 않음값을 변경하면 컴포넌트를 다시 렌더링
주요 사용 사례DOM 엘리먼트 접근, 렌더링과 무관한 값 관리상태 관리, 값 변경 시 UI 업데이트
비교주로 렌더링과 관계없는 데이터 저장UI 업데이트를 위한 상태 관리