Frontend Study - 2/React

React : useRef. 값이 변경되어도 렌더링 되지 않는 변수 만들기.

갓데미 2022. 7. 24. 20:31

1) 다시 렌더링이 되어도 동일한 참조값 유지.

 

React 컴포넌트는 State가 변할 때마다 다시 렌더링이 되고 내부의 변수들이 초기화 됩니다.

이것을 원하지 않을 때 useRef 를 사용할 수 있습니다. Ref 안의 값이 변경 되어도 컴포넌트는 다시 렌더링 되지 않습니다.

불필요한 렌더링이라면 State대신 Ref를 사용해서 막을 수 있습니다. 

mport React, { useState, useEffect } from "react";

function ManualCounter() {
  const [count, setCount] = useState(0);

  let intervalId;

  const startCounter = () => {
    // 💥 매번 새로운 값 할당
    intervalId = setInterval(() => setCount((count) => count + 1), 1000);
  };
  const stopCounter = () => {
    clearInterval(intervalId);
  };

  return (
    <>
      <p>자동 카운트: {count}</p>
      <button onClick={startCounter}>시작</button>
      <button onClick={stopCounter}>정지</button>
    </>
  );
}

 

위 코드에서 중요한 것은 선언된 intervalid 변수를 startCounter() 함수와 stopCounter() 함수가 공유할 수 있도록 해줘야 한다는 것입니다. 그럴려면 intervalId 변수를 두 함수 밖에서 선언해야하는데 그럴 경우, count 상태값이 바뀔 때 마다 컴포넌트 함수가 호출되어 intervaiId도 매번 새로운 값으로 바뀔 것입니다. 브라우저 메모리에는 미처 정리되지 못한 intervalid 들이 1초에 하나식 쌓여나갈 것입니다. 

 

useRef 함수는 current 속성을 가지고 있는 객체를 반환하는데, 인자로 넘어온 초기값을 current 속성에 할당합니다. 이 current 속성은 값을 변경해도 상태를 변경할 때 처럼 React 컴포넌트가 다시 렌더링되지 않습니다.

React 컴포넌트가 다시 렌더링될 때도 마찬가지로 이 current 속성의 값이 유실되지 않습니다.

 

아래 코드를 보면 처음에 useRef(null)로 설정해 주었는데

useState로 설정해 주었다면 계속해서 렌더링이 일어났었을 것이다.

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

function ManualCounter() {
  const [count, setCount] = useState(0);
  const intervalId = useRef(null);
  console.log(`랜더링... count: ${count}`);

  const startCounter = () => {
    intervalId.current = setInterval(
      () => setCount((count) => count + 1),
      1000
    );
    console.log(`시작... intervalId: ${intervalId.current}`);
  };

  const stopCounter = () => {
    clearInterval(intervalId.current);
    console.log(`정지... intervalId: ${intervalId.current}`);
  };

  return (
    <>
      <p>자동 카운트: {count}</p>
      <button onClick={startCounter}>시작</button>
      <button onClick={stopCounter}>정지</button>
    </>
  );
}

 

2) DOM 요소에 접근.

 

useRef() 를 사용하여 Ref 객체를 만들고, 이 객체를 우리가 선택하고 싶은 DOM 에 ref 값으로 설정해주어야 합니다.

그러면, Ref 객체의 .current 값은 우리가 원하는 DOM 을 가르키게 됩니다. 대표적으로 input요소를 클릭하지 않고 포커스를 주고 싶을 때 많이 사용됩니다. 

 

 const nameInput = useRef();
 nameInput.current.focus();
  <input
        name="name"
        placeholder="이름"
        onChange={onChange}
        value={name}
        ref={nameInput}
      />