본문 바로가기

Front-end/React

useRef 사용법

uesRef는 component의 entire lifetime동안 지속되는 object를 생성한다. (component의 unmount까지 유지된다.)

 

하지만 obejct의 current 속성을 이용해 변수의 값에 접근할 수 있다.

 

useRef로 생성된 object는 state와 다르게 component의 re-render시에도 변하지 않는다. (re-render에 영향을 받지 않는다.)


import { useState,useRef } from "react";

export default function MyComponent_19_1(){

  const [count,SetCount] = useState(0)
  const countRef = useRef(0)
  let countVar = 0

  const incrementCountState =  () => {
    SetCount(count + 1)
  }
  
  const incrementCountRef = () => {
    countRef.current = countRef.current + 1
  }

  const incrementCountVar = ()  => {
    countVar = countVar + 1
  }
  return(
    <div>
      <p>State: {count}</p>
      <p>Ref: {countRef.current}</p>
      <p>Var: {countVar}</p>
      <button onClick={incrementCountState}>State 증가</button>
      <button onClick={incrementCountRef}>Ref 증가</button>
      <button onClick={incrementCountVar}>Var 증가</button>
    </div>
  )
}

 

위의 예제 코드에서 State 증가 버튼이 클릭되면 incrementCountState 함수에서 setCount가 실행된다.

이 때 state가 변경되었기 때문에 component는 re-render된다.

 

Ref 증가 버튼이 클릭되면 incrementCountRef 함수에서 countRef의 current 속성의 값이 1 증가한다.

이 때 component는 re-render되지 않으므로 <p> element 안의 countRef.current 값은 변하지 않는다. (실제로는 바뀌지만 화면에 보여지지 않음)

component가 re-render될 시 이전의 값이 남아있기 때문에 값이 계속 더해진다.

 

Var 증가 버튼이 클릭되면 incrementCountVar 함수에서 countVar의 값이 1 증가한다.

하지만 component는 re-render되지 않으므로 <p> 안의 countVar는 변하지 않는다.

component가 re-render될 시 countVar 변수도 함께 0으로 초기화된다. 

 

 

useRef는 re-render에 영향을 받지 않으면서 값에 접근할 수 있는 Object를 생성한다.

 

또한 useRef로 만들어진 current의 값이 바뀔 때 component는 re-render되지 않는다.

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

export default function MyComponent_19_2(){

  const [count,setCount] = useState(0)
  const [renderCount,setRenderCount] = useState(0)
  const renderRef = useRef(0)

  // 의존성 배열이 생략되었으므로 컴포넌트 업데이트시마다 실행
  // 생성시 초기값 0, 생성후 실행되므로 1
  useEffect(()=>{
    // console.log('렌더링:',renderCount)
    // setRenderCount(renderCount+1)
    console.log('렌더링:',renderRef.current)
    renderRef.current = renderRef.current + 1
  })

  return(
    <div>
      <p>State: {count}</p>
      <p>render State: {renderCount}</p>
      <p>Ref: {renderRef.current}</p>
      <button onClick={() => setCount(count + 1)}>State Count 증가</button>
    </div>
  )
}

 

위의 코드에서 useEffet는 component의 render마다 실행된다.

만약 setRenderCount를 useEffect 안에서 사용하면 state가 바뀌므로 componenet를 rerender한다.

이것은 useEffect를 다시 실행시키므로 결국 renderCount의 값은 무한으로 증가한다.

 

이 때 setRenderCount 대신 ref 변수의 값을 1 증가시킨다면 이것은 rerender를 발생시키지 않으므로 정상적으로 작동한다.

변화는 감지해야 하지만 그 변화가 랜더링을 발생시키면 안되는 경우 사용할 수 있다.

useRef의 쓰임 by ChatGPT

 

  1. Accessing DOM elements: You can use useRef to get references to DOM elements and interact with them imperatively. This can be useful for focusing elements, measuring their dimensions, or animating them.
  2. Storing mutable values: useRef can store values that persist across renders without causing re-renders. This is useful for storing values that you want to persist between renders but don't need to be part of the component's state.
  3. Keeping track of previous values: You can use useRef to store values that need to persist across renders for comparison purposes. This is often used in useEffect hooks to compare previous and current values.
  4. Optimizing performance: In some cases, useRef can be used to optimize performance by memoizing values or references that don't need to trigger re-renders.
  5. Caching expensive computations: You can use useRef to cache the result of expensive computations so that they don't need to be recomputed on every render.
  6. Storing mutable data for third-party libraries: If you're using a third-party library that requires mutable data, you can use useRef to store that data without triggering re-renders.

3의 예제

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

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

  useEffect(() => {
    // Store the current count in the ref before it changes
    countRef.current = count;

    // Log the previous and current count
    console.log("Previous count:", countRef.current);
    console.log("Current count:", count);
  }, [count]);

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

export default Example;

 

5의 예제

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

function Example() {
  const [count, setCount] = useState(0);
  const [result, setResult] = useState(null);
  const computationCache = useRef({});

  useEffect(() => {
    // Check if the result for the current count is already cached
    if (computationCache.current[count] !== undefined) {
      // If it's cached, use the cached result
      setResult(computationCache.current[count]);
    } else {
      // If it's not cached, perform the expensive computation
      const computedResult = expensiveComputation(count);

      // Cache the result for future use
      computationCache.current[count] = computedResult;

      // Update the result state
      setResult(computedResult);
    }
  }, [count]);

  // Example of an expensive computation function
  function expensiveComputation(input) {
    console.log("Performing expensive computation for input:", input);
    // Simulate an expensive computation
    return input * 2;
  }

  return (
    <div>
      <p>Count: {count}</p>
      <p>Result of Expensive Computation: {result}</p>
      <button onClick={() => setCount(count + 1)}>Increment Count</button>
    </div>
  );
}

export default Example;

'Front-end > React' 카테고리의 다른 글

Zustand 사용  (0) 2024.04.04
Axios로 서버에 http 요청 보내기  (1) 2024.04.02