하다보니

[React Hooks]useRef 본문

프로그래밍 언어/React

[React Hooks]useRef

claire 2022. 7. 6. 12:14

함수형 컴포넌트에서 useRef를 부르면 ref 오브젝트를 반환해준다. 

const ref=useRef(value)

ref는 {current:value} 형태이다. 우리가 초기값으로 넣어준 value는 ref의 current에 저장이 된다. ref 오브젝트는 언제든 수정이 가능하다. 반환된 fref는 컴포넌트의 전 생애 주기를 통해 유지가 된다. 컴포넌트가 계속해서 렌더링이 되어도 컴포넌트가 unmount 되기 전까지는 값을 유지할 수 있다. 

useRef의 사용

1. 저장공간

state의 변화->렌더링->컴포넌트 내부 변수들 초기화

따라서 원하지 않은 렌더링으로 곤란해질 수 있다. 

Ref의 변화-> no 렌더링-> 변수들의 값이 유지됨

불필요한 렌더링 막을 수 있음

state변화->렌더링->그래도 Ref의 값은 유지됨

 

<useRef 사용 예시>

import { useState, useRef } from "react";
const App = () => {
  const [count, setCount] = useState(0);
  //countRef.current로 접근 가능
  const countRef = useRef(0);

  const increaseCountState = () => {
    setCount(count + 1);
  };

  //ref는 아무리 수정을 해도 화면이 업데이트 되지 않는다. 그래서 아무리 눌러도 화면이 갱신이 안된다.
  // ref는 엄청 자주 바뀌는 값이어도 렌더링이 발생하지 않기 때문에 성능 향상에 좋다.
  const increaseCountRef = () => {
    countRef.current = countRef.current + 1;
  };

  return (
    <div>
      <p>State:{count}</p>
      <p>Ref:{countRef.current}</p>
      <button onClick={increaseCountState}>State 올려</button>
      <button onClick={increaseCountRef}>Ref 올려</button>
    </div>
  );
};

export default App;

<useRef와 일반 변수 차이>

import { useState, useRef } from "react";

// useRef와 컴포넌트 변수의 차이
const App = () => {
  const [renderer, setRenderer] = useState(0);
  const countRef = useRef(0);
  let countVar = 0;

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

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

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

  return (
    <div>
      <p>Ref:{countRef.current}</p>
      <p>Var:{countVar}</p>
      <button onClick={doRendering}>렌더!</button>
      <button onClick={increaseRef}>Ref 올려</button>
      <button onClick={increaseVar}>Var 올려</button>
    </div>
  );
};

export default App;

컴포넌트가 렌더링 된다는 것은 컴포넌트 함수가 다시 불린다는 것이다. 함수가 불릴때마다 함수 내부의 변수는 초기화가 된다. 하지말 ref는 컴포넌트가 아무리 렌더링되어도 값을 유지한다. ref의 값은 컴포넌트의 전 생애 주기를 통해 유지가 된다. 컴포넌트가 브라우저에 mounting 된 시점부터 mount 해제될 때까지 같은 값을 유지할 수 있다. 

 

<useState와 useEffect 무한루프>

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

const App = () => {
  const [count, setCount] = useState(1);
  const renderCount = useRef(1);
  // const [renderCount, setRenderCount] = useState(1);

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

  // 무한 루프에 갇힘. renderCount변화->useEffect불림->renderCount 변화->useEffect 불림....
  // useEffect(() => {
  //   console.log("렌더링");
  //   setRenderCount(renderCount + 1);
  // });

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

export default App;

useRef는 변화는 감지해야하지만 그 변화가 렌더링을 발생시키면 안되는 값을 다룰 때 편리하다. 

 

2. DOM 요소에 접근

input 요소를 클릭하지 않아도 focus를 주고 싶을 때와 같은 상황에 사용 가능. 

 

useRef가 반환하는 ref 오브젝트를 우리가 접근하고자 하는 요소 태그에 ref 속성으로 넣어주기만 하면 쉽게 해당 요소에 접근할 수 있다. 

vanilla JS의 document.querySelector와 같이 동작할 수 있다. 

import { useEffect, useRef } from "react";
const App = () => {
  const inputRef = useRef();

  useEffect(() => {
    inputRef.current.focus();
  }, []);

  const login = () => {
    alert(`환영합니다 ${inputRef.current.value}`);
    inputRef.current.focus();
  };

  return (
    <div>
      <input ref={inputRef} type="text" placeholder="username" />
      <button onClick={login}>로그인</button>
    </div>
  );
};

export default App;

 

'프로그래밍 언어 > React' 카테고리의 다른 글

[React Hooks]useCallback  (0) 2022.07.12
[React Hooks]useMemo  (0) 2022.07.07
[React Hooks]useContext  (0) 2022.07.06
[React hooks]useEffect  (0) 2022.07.06
[React Hooks]useState  (0) 2022.07.05