dukDukz

[React hook] useRef - 리렌더 방지 본문

웹 개발/React

[React hook] useRef - 리렌더 방지

헤일리_HJ 2022. 1. 25. 11:43

1. useState 와 useRef

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

function TestRef() {
  const [count, setCount] = useState(0);
  const countRef = useRef(0);

  const increaseCountState = () => { // 누르면 즉시 렌더링됨
    setCount(count + 1);
  };

  const increaseCountRef = () => { // 눌러도 컴포넌트가 렌더링 되지 않음
    countRef.current += 1;
    console.log('ref == ', countRef.current);
  };

  return (
    <div>
      <p> state :{count} </p>
      <p> Ref :{countRef.current} </p>
      <button type="button" onClick={increaseCountState}> state 올려 </button>
      <button type="button" onClick={increaseCountRef}> ref 올려 </button>

    </div>
  );
}

export default TestRef;

-> 렌더링이 너무 많이 되면 성능이 떨어질 수 있기 때문

 

useState는 값이 변할 때 마다 렌더링이 계속 일어나고 화면에 표출된다.

반면에 useRef는 값이 변하지만 렌더링이 일어나지 않아 화면에 표출 되지 않는다.

 

이렇게 useRef를 이용하면 값이 변하지만 리렌더 되지 않아 화면에서는 확인 할 수 없다.

 

 


 

2. let 과 useRef

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

function TestRef2() {
  const countRef = useRef(0);
  let countVar = 0;
  const [renderer, setRenderer] = useState(0);

  const doRender = () => {
    setRenderer(renderer + 1);
  };

  const increaseRef = () => {
    countRef.current += 1;
    console.log('ref ==', countRef.current);
  };

  const increaseVar = () => {
    countVar += 1;
    console.log('countVar === ', countVar);
  };

  const printResult = () => {
    console.log(`ref === ${countRef.current}, var === ${countVar}`);
  };

  return (
    <div>
      <p> Ref : {countRef.current}</p>
      <p>Var : {countVar}</p>

      <button type="button" onClick={doRender}>렌더</button>
      <button type="button" onClick={increaseRef}>Ref 올려</button>
      <button type="button" onClick={increaseVar}>Var 올려</button>
      <button type="button" onClick={printResult}>Ref Var 값 출력</button>
    </div>
  );
}

export default TestRef2;

 

useRef 와 let 변수 모두 리렌더를 발생시키지 않는다.

하지만 값은 변하고 있다.

 

 

Ref 올려

Var 올려

둘을 누르면 값이 각각 변하는것을 콘솔에서 확인 할 수 있다.

 

하지만 화면에서는 확인 할 수 없다.

강제로 렌더를 시켜주는 함수를 만들어서 ,useState 사용, 렌더 해주면  

 

 

헉... 뭐야..!!! 왜 Ref만 값이 업데이트 되고 let 선언한거는 안나오지...?

라고 할 수 있겠지만

사실은 리렌더 되면서 let 변수 선언한 녀석의 값이 초기화 된 것이다.

반면에 useRef 사용한 녀석은 값이 유지된다.

 

 콘솔을 보면 확인이 가능하다.

 

 


 

3.  useEffect 리렌더 지옥

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

function TestRef3() {
  const [count, setCount] = useState(1);
  const [renderCount, setRenderCount] = useState(1);

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

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

export default TestRef3;

setCount 로 업데이트 되고,

useEffect 안에 배열을 생략한다면 리렌더링 될때마다 실행된다.

근데 setRenderCount 로 값을 업뎃시켜주면서 렌더를 시키니까 이게 무한으로 리렌더 되는 것

 

이러면 정상작동이 안되고

 

 

 

 

이렇게 바꿔줘야 한다.

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

function TestRef3() {
  const [count, setCount] = useState(0);
  const renderCount = useRef(0);

  useEffect(() => {
    renderCount.current += 1;
    console.log('렌더링 수 : ', renderCount.current);
  });

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

export default TestRef3;

 

useRef로 바꾸면 ... 값은

 

renderCount를 useRef로 바꾸면

변화는 감지하지만 그 변화가 리렌더링을 발생시키지 않는 값을 다룰 때 편리하게 사용가능하다.