Notice
Recent Posts
Recent Comments
관리 메뉴

즐겁게, 코드

useRef 훅에 대하여 본문

🎨 프론트엔드/React.js

useRef 훅에 대하여

Chamming2 2021. 1. 1. 19:37

useRef 훅은 마치 북극성에 비유할 수 있는 훅이다.

훅을 소개하기 앞서 코드를 하나 살펴보자.

import React, { useState } from "react";

function UseRef() {
  const [name, setName] = useState("");

  return (
    <>
      <input value={name} onChange={(e) => setName(e.target.value)}></input>
      <div>이름 : {name}</div>
    </>
  );
}

export default UseRef;

이름을 입력받는 입력란과 이름을 출력하는 요소가 있다.

만약 상태가 업데이트될 때마다 컴포넌트가 렌더링되는 횟수를 구해야 한다면, 어떻게 구할 수 있을지 잠깐 생각해보자.

 

아마 useRef를 모르는 사람이라면 이렇게 코드를 작성할 것이다. (실제로 나도 이렇게 작성했었다.)

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

function UseRef() {
  const [name, setName] = useState("");
  const [renderCount, setRenderCount] = useState(1);
  
  useEffect(() => {
    setRenderCount((prev) => prev + 1);
  });

  return (
    <>
      <input value={name} onChange={(e) => setName(e.target.value)}></input>
      <div>이름 : {name}</div>
      <div>렌더링 횟수 : {renderCount}번</div>
    </>
  );
}

export default UseRef;

이름을 수정할 때마다 useEffect 훅에서 렌더링 횟수가 업데이트되고 얼핏 보면 성공적으로 렌더링 횟수를 구하는 것처럼 보인다.

 

그러나 잘 생각해보면 renderCount 역시 상태값이므로 renderCount가 업데이트되면 렌더링 횟수가 또 올라가게 되고, 이는 결국 무한히 재귀적인 렌더링으로 이어져 에러를 출력하게 된다.

답이 없어보이는 이 문제는 useRef를 사용하면 아주 간단하게 렌더링 횟수를 구할 수 있다.

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

function UseRef() {
  const [name, setName] = useState("");
  const renderCount = useRef(0);

  useEffect(() => {
    renderCount.current += 1;
  }, [name]);

  return (
    <>
      <input value={name} onChange={(e) => setName(e.target.value)}></input>
      <div>이름 : {name}</div>
      <div>렌더링 횟수 : {renderCount.current}번</div>
    </>
  );
}

export default UseRef;

useRef 값의 변경은 컴포넌트를 재렌더링하지 않으며, 렌더링에 영향을 받지도 않는다.

즉 컴포넌트의 업데이트에 따른 부수효과(Side effect)의 영향을 받아서는 안되는 값은 useRef를 통해 사용할 수 있다.

 

[useRef 훅의 사용법]

import React, { useRef } from "react"

const value = useRef(초기값);
// useRef로 사용한 값은 current 속성값을 통해 조작한다.
value.current = value.current + 1; 

물론 실제 코드를 짤 때 컴포넌트의 렌더링 횟수를 구해야 하는 일은 드물다.

useRef 훅은 주로 DOM 요소를 직접 조작해야 할 때 사용되는데, document.querySelector() 등으로 DOM을 직접 선택하는 것은 리액트의 안티패턴 중 하나다.

 

(돔 요소를 직접 수정하게 되면 비즈니스 로직과 UI를 수정하는 코드가 뒤섞여 복잡해진다.)

import React, { useState } from "react";

function UseRef() {
  const [name, setName] = useState("");

  return (
    <>
      <input value={name} onChange={(e) => setName(e.target.value)}></input>
      <div>이름 : {name}</div>
      <button>포커스 이동</button>
    </>
  );
}

export default UseRef;

이번에는 useRef를 활용해 버튼을 누르면 입력창에 포커스가 맞춰지도록 코드를 짜보자.

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

function UseRef() {
  const [name, setName] = useState("");
  const inputRef = useRef(null);

  return (
    <>
      <input
        ref={inputRef}
        value={name}
        onChange={(e) => setName(e.target.value)}
      ></input>
      <div>이름 : {name}</div>
      <button onClick={() => inputRef.current.focus()}>포커스 이동</button>
    </>
  );
}

export default UseRef;

이렇게 useRef를 사용한 변수를 요소의 참조라고 생각해 ref = {inputRef} 로 사용한 모습이다.

이제 저 입력창은 inputRef.current 를 통해 어떤 부작용도 없이 조작할 수 있게 되었다.

반응형

'🎨 프론트엔드 > React.js' 카테고리의 다른 글

defaultProps에 대한 짧은 고찰  (0) 2021.01.31
useContext 훅에 대하여  (0) 2021.01.05
useMemo 훅에 대하여  (0) 2020.12.30
Portal 사용하기  (0) 2020.12.28
useEffect 훅에 대하여  (1) 2020.12.28
Comments
소소한 팁 : 광고를 눌러주시면, 제가 뮤지컬을 마음껏 보러다닐 수 있어요!
와!! 바로 눌러야겠네요! 😆