[React] Hooks(2) useRef

JiHyun·2023년 3월 2일
0
post-thumbnail

별코딩 React Hook강의
본 내용은 별코딩님의 React Hook강의를 참고하여 작성하였습니다.


useRef

const ref = useRef(value);

console.log(ref)  // { current : value }
ref.current = 'jihyun'  // { current : 'jihyun' }

useRef는 객체로 형성된다. useRef의 인자로 넣어준 값은 ref의 current 프로퍼티의 값으로 들어가게 된다.

useRef는 언제 사용될까?

1. 저장공간

state와 비슷하게 어떠한 값을 저장해두는 저장공간으로 쓰인다. state를 변경하면 자동으로 컴포넌트가 리렌더링되고 컴포넌트 내부 변수들이 초기화되는데 원하지 않은 렌더링때문에 곤란해질때가 있는데 이때 state대신 ref에 값을 저장하면 리렌더링이 되지 않고 변수들의 값은 그대로 유지된다.
또한 state가 변해서 렌더링이 되더라도 ref의 값은 계속 유지된다.

state의 변화 -> 렌더링 -> 컴포넌트 내부 변수들 초기화
Ref의 변화 -> 렌더링X -> 변수들의 값이 유지됨

이처럼 state올려 버튼을 누르면 state는 화면에서 계속 렌더링되서 올라가지만 Ref올려 버튼을 아무리 눌러도 화면에서 ref의 변화가 없다. 그러다 화면이 렌더링되면 Ref의 값이 바뀐다.
실제로는 ref의 객체내에 프로퍼티 값이 변화하지만 렌더링이 되지 않기때문에 변화가 없는 것처럼 보이는 것이다.
변수로 선언한 var역시도 'var 올려' 버튼을 아무리 눌러도 그 값은 올라가지 않는 것 처럼 보이지만 콘솔에서는 var의 변화를 볼 수 있다. 하지만 ref랑 다르게 렌더링이 되면 변수는 초기화되기 때문에 화면에서는 var의 값이 바뀌지 않는것이다.

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

export default function App() {
  const [count, setCount] = useState(1);
  const [renderCount, setRenderCount] = useState(0);

  useEffect(() => {
    setRenderCount(renderCount + 1);
    console.log("렌더링 수:" + renderCount);
  });

  return (
    <div>
      <p>Count : {count}</p>
      <button onClick={() => setCount(count + 1)}>올려</button>
    </div>
  );
}

count라는 변수를 증가시키는 코드를 만들었다. 그리고 렌더링이 몇번이 되는지를 확인하려고 한다.
여기서 renderCount를 useState에 저장하고 실행해보면 어떻게 될까?
먼저 useEffect는 렌더링이 될때마다 콜백함수를 실행한다. 화면이 처음 렌더링이 되고 useEffect안에 있는 콜백함수가 실행되고 콜백함수는 renderCount의 값을 변화시켜주니 또 리렌더링이 되고 useEffect가 실행되고...를 반복하며 무한 루프에 빠지게 될 것이다.

이럴때 콜백함수에 ref를 사용해서 리렌더링을 막으면 무한루프에 빠지지 않고 renderCount의 값이 잘 저장되는걸 볼 수 있다.
이처럼 ref의 값이 변해도 렌더링이 되지 않는 이유는 무엇일까?
우선 ref는 객체로 저장되어있다. 객체는 값이 변해도 메모리 주소값은 바뀌지 않아서 리액트는 객체의 변화를 감지하지 못하게 되고 렌더링이 진행되지 않는다. 정말 놀랍지 않은가? 앞서 배웠던 불변성의 개념이 이렇게 쓰이다니! 이론공부가 필요한 이유가 여기 있었다.

2. DOM 요소에 접근

리액트는 virtual DOM(가상돔)을 통하여 DOM을 수정, 생성한다. 하지만 가끔씩은 DOM 을 직접 선택해야하는 경우도 있다. (예를들어 스크롤바 위치를 가져오거나 설정해야된다던지, 포커스를 설정해야 한다던지 등등) 이런 상황에서 useRef를 사용해 DOM요소에 접근할 수 있다. 마치 바닐라js의 document.querySelector()와 같은 역할을 하는 것이다.


여기 대표적으로 ref를 활용한 DOM요소에 접근하는 예시이다.
화면이 렌더링되면 input박스에 자동으로 focus가 되게 해준다. input박스에 ref를 넣어주고 화면이 렌더링되면 useEffect가 실행되며 콜백함수로 인해 input박스에 focus가 된다.

profile
비전공자의 개발일기📝

0개의 댓글