프론트엔드 개발일지 #35 - useRef

조아라·2024년 11월 1일
0
post-thumbnail

useRef

렌더링에 필요하지 않은 값을 참조할 수 있는 React Hook 😯

1. ref로 값 참조하기

컴포넌트의 최상위 레벨에서 useRef를 호출하여 하나 이상의 ref를 선언한다.

import { useRef } from 'react';

function Stopwatch() {
  const intervalRef = useRef(0);

💡useRef는 처음에 제공한 초기값으로 설정된 단일 current 프로퍼티가 있는 ref 객체를 반환한다.

💡다음 렌더링에서 useRef는 동일한 객체를 반환하고, 정보를 저장한다. 나중에 읽을 수 있도록 current 속성을 변경할 수 있다.

그럼 state와 뭐가 다른걸까❔
ref를 변경해도 리렌더링✖️
➡️ref는 컴포넌트의 시각적 출력에 영향을 미치지 않는 정보를 저장하는 데 적합하다.

예시

  1. counter 클릭하기
    ref를 사용하여 버튼이 클릭된 횟수를 추적한다. 클릭 횟수는 이벤트 핸들러에서만 읽고 쓰기 때문에 여기서는 state 대신 ref를 사용❗
import { useRef } from 'react';

export default function Counter() {
  let ref = useRef(0);

  function handleClick() {
    ref.current = ref.current + 1;
    alert('You clicked ' + ref.current + ' times!');
  }

  return (
    <button onClick={handleClick}>
      Click me!
    </button>
  );
}
  1. 스톱워치
    startTime과 now는 모두 렌더링에 사용되기 때문에 state 변수. 그러나 버튼을 누를 때 interval을 멈출 수 있게 하기 위해선 interval ID도 보유해야 한다. interval ID는 렌더링에 사용되지 않으므로 ref에 보관하고 수동으로 업데이트하는 것이 적절하다😯
import { useState, useRef } from 'react';

export default function Stopwatch() {
  const [startTime, setStartTime] = useState(null);
  const [now, setNow] = useState(null);
  const intervalRef = useRef(null);

  function handleStart() {
    setStartTime(Date.now());
    setNow(Date.now());

    clearInterval(intervalRef.current);
    intervalRef.current = setInterval(() => {
      setNow(Date.now());
    }, 10);
  }

  function handleStop() {
    clearInterval(intervalRef.current);
  }

  let secondsPassed = 0;
  if (startTime != null && now != null) {
    secondsPassed = (now - startTime) / 1000;
  }

  return (
    <>
      <h1>Time passed: {secondsPassed.toFixed(3)}</h1>
      <button onClick={handleStart}>
        Start
      </button>
      <button onClick={handleStop}>
        Stop
      </button>
    </>
  );
}

2. ref로 DOM 조작하기

  1. 텍스트 input에 초점 맞추기

    버튼을 클릭하면 입력에 초점이 맞춰진다.

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>
    </>
  );
}
  1. 이미지 스크롤하기

버튼을 클릭하면 이미지가 스크롤 된다. 목록 DOM 노드에 대한 ref를 사용한 다음 DOM querySelectorAll API를 호출하여 스크롤하려는 이미지를 찾는다.

import { useRef } from 'react';

export default function CatFriends() {
 const listRef = useRef(null);

 function scrollToIndex(index) {
   const listNode = listRef.current;
   // 다음 코드는 특정 DOM 구조를 가정합니다:
   const imgNode = listNode.querySelectorAll('li > img')[index];
   imgNode.scrollIntoView({
     behavior: 'smooth',
     block: 'nearest',
     inline: 'center'
   });
 }

 return (
   <>
     <nav>
       <button onClick={() => scrollToIndex(0)}>
         Neo
       </button>
       <button onClick={() => scrollToIndex(1)}>
         Millie
       </button>
       <button onClick={() => scrollToIndex(2)}>
         Bella
       </button>
     </nav>
     <div>
       <ul ref={listRef}>
         <li>
           <img
             src="https://placecats.com/neo/300/200"
             alt="Neo"
           />
         </li>
         <li>
           <img
             src="https://placecats.com/millie/200/200"
             alt="Millie"
           />
         </li>
         <li>
           <img
             src="https://placecats.com/bella/199/200"
             alt="Bella"
           />
         </li>
       </ul>
     </div>
   </>
 );
}
profile
끄적 끄적 배운 걸 적습니다 / FRONT-END STUDY VELOG

0개의 댓글