프로그래밍

useRef 사용용도

useRef는 주로 DOM 엘리먼트를 직접 조작하고 싶을 때 사용한다.

그것 외의 사용처는 없는 줄 알았는데 useInterval 게시글 보다가 알게됨. (velog.io/@jakeseo_me/%EB%B2%88%EC%97%AD-%EB%A6%AC%EC%95%A1%ED%8A%B8-%ED%9B%85%EC%8A%A4-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EC%97%90%EC%84%9C-setInterval-%EC%82%AC%EC%9A%A9-%EC%8B%9C%EC%9D%98-%EB%AC%B8%EC%A0%9C%EC%A0%90)

 

훅스에서 ref는 변환가능한 current 프로퍼티를 가지는 순수한 오브젝트를 반환한다. 

리액트의 컴포넌트는 리렌더링시에 모든 변수를 삭제하고 다시 생성해서 할당시키기 때문에 로컬 변수를 업데이트하고 유지할 수 없다.

ref의 current공간은 리렌더링을 해도 그 전값이 유지가 된다.

state처럼 변경되고 유지가 되는 변수가 필요하지만 변경시에 리렌더링을 하고 싶지 않을때 useRef가 유용하다.

 

예시

 

import React, {useState, useEffect} from 'react'

function App() {
  const [stateNum, setState] = useState(0)
  const obj = {num: 0}
  let num = 0

  const onClickFunc = () => {
    num += 1;
    obj.num += 1;
    setState(stateNum + 1)
  }

  return (
    <div className="App">
      <p>
        stateNum : {stateNum}
      </p>
      <p>
        obj.num : {obj.num}
      </p>
      <p>
        local num : {num}
      </p>
      <button onClick={onClickFunc}>클릭</button>
    </div>
  );
}

export default App;

 

클릭 버튼을 누르면 stateNum, obj.num, 로컬변수 num이 +1씩 증가시킨다.

 

 

 

하지만 클릭하면 obj.num과 local num은 값이 변하지 않는다.

그 이유는 state가 리렌더링 될 때마다 값이 제거되고 새로 초기화값인 0으로 할당받기 때문이다.

 

 

useRef는 리렌더링이 되어도 제거되지 않는 공간을 제공한다.

이 공간에 값을 저장하고 current 프로퍼티로 꺼내는 방식으로 로컬변수처럼 사용할 수 있다.

 

 

import React, {useState, useEffect, useRef} from 'react'


function App() {
  const [stateNum, setState] = useState(0)

  const obj = {num: 0}
  let num = 0
  const refNum = useRef(0)

  const onClickFunc = () => {
    num += 1;
    obj.num += 1;
    refNum.current += 1
    setState(stateNum + 1)
  }

  return (
    <div className="App">
      <p>
        stateNum : {stateNum}
      </p>
      <p>
        obj.num : {obj.num}
      </p>
      <p>
        local num : {num}
      </p>
      <p>
        useRef num : {refNum.current}
      </p>
      <button onClick={onClickFunc}>클릭</button>
    </div>
  );
}

export default App;

 

useRef의 변수는  잘 작동한다.

 

 

 

어느 경우에 이게 유용할까?

내 생각에 값이 업데이트 되고 그 값이 유지되어야 하긴 하지만 바뀔때마다 리렌더링될 필요는 없는 경우에 이걸 써먹으면 좋다.

 

예시

const onClickFunc = () => {
    num += 1;
    obj.num += 1;
    refNum.current += 1
    console.log(num, obj.num, refNum.current)
    if(refNum.current % 5 === 0) setState(stateNum + 1)
  }

위 코드의 온클릭 함수인데 클릭을 5의 배수로 할 경우에만 리렌더링 하고싶다면 refNum값을 업데이트 하다가 조건을 만족했을때 state를 수정하면 된다.

 

위 코드결과

 

리렌더링은 5, 10, 15일때 딱 세번된다.

로컬 변수들은 리렌더링시 값이 초기화 되어서 0부터 다시 시작하는 모습이지만 ref에 저장한 변수는 값이 유지되는 걸 확인할 수 있다.