TIL

useState()와 useRef

inz1234 2024. 2. 1. 22:08

useSate

- state의 상태를 저장하는 기능

- state의 상태가 바뀔 때마다 렌더링 됨

 

useRef

1. 저장공간

- state와 비슷하게 저장기능이 있음

- But, ref에 저장한 값은 바꾸더라도 re-렌더링 되지 않음(= 페이지의 다른 변수들이 초기화되지 않음)

- 거꾸로, 100번 렌더링 되어도 ref에 저장한 값은 유지됨

- 개인적인 생각으로 state는 "상태" 를 저장하는 것인데, ref는 "값"을 저장하는 느낌

=> useState는 리렌더링이 꼭 필요한 변수에 사용하고,

     useRef 리렌더링이 굳이 필요하지 않은 변수에 사용하면 좋을 것 같음 (ex. id, 비밀번호.. etc)

 

2. DOM 요소의 접근 수단

- 리액트를 배우기 전 vanilla javascript에서 썼던 getElementById, QuerySelector와 같이 특정 컴포넌트에 접근하고자 할 때, useRef를 이용해서 그 주소를 참조할 수 있음

 

 

 

개인적인 생각

- 둘 다 장단점이 있는 것 같다.

 

- 물론 useRef가 state의 변경될 때마다 re-렌더링이 되지 않아서 값을 초기화시키지 않는다는 장점이 있지만,

다른 한편으로는 예를 들어 어떤 버튼을 클릭해서 변화를 주고자 할 때, useRef는 값을 수정한다고 해도 화면에 변화가 나타나지 않아서 UI적으로는 useState에 비해 별로 효과적이지 않을 것 같다. 

각각의 장단점이 있어서 상황에 맞게 사용하는 것이 가장 best일 듯 하다.

 

- 반면, useRef를 사용하면 이전값을 기억한다는 장점으로 인해 setState라면 날라가버릴 이전값과 현재값 비교할 수 있을 것 같다.

아니면 뭐.. setState로 저장한 값을 useRef에 저장하는 함수로직을 만들어서 상태가 변화될 때마다 그 값을 저장하여 추적? 할 수 있을지도..? 만약 그게 된다고 하면 댓글 같은 경우, 또는 뭐 인터넷 사용경로 등을 기억할 수 있을 것 같다.

 

- 개인적으로 useRef의 장점이라고 생각이 드는 것은, useState를 사용해서 화면을 리렌더링할 때 state의 형태가 객체나 배열이면 데이터 주소의 불변성 유지를 위해서 얕은복사를 한 후 setState를 해야하는 번거로움이 있다.

간단한 배열이나 객체면 괜찮지만 복잡한 객체라면, 전개연산자 사용, 새로운 배열 또는 객체 안에 넣어서 저장하는 것이 헷갈린다ㅠ

 

 

구현코드

 

import "./App.css";
import { useState, useRef, useEffect } from "react";

 

function App() {
  const [count, setCount] = useState(0);
  const refCount = useRef(0);

 

  // useRef의 예시
  // 1. 저장공간으로서의 사용
  const nickName = useRef("저팔개");
  console.log(nickName); // {current : "저팔개"}

 

  // 2. DOM요소의 접근수단으로서의 사용
  //
  const inputRef = useRef("사과");
  useEffect(() => {
    inputRef.current.focus();
  }, []);

 

  return (
    <>
      <h2>0. useState 예시</h2>
      {/* useState 예시 */}
      <button
        onClick={() => {
          setCount(count + 1);
          refCount.current++;
          // 단 이렇게 setCount랑 ref의 값을 변경하는 로직이 같은 함수에 있으면, state가 변경되면서 렌더링이 되므로 바뀐 ref값도 바로 보여짐
          // => ref도 렌더링이 되면 변경된 값을 보여준다. 변경될 때마다 렌더링이 되지 않을 뿐
          console.log(refCount.current);
        }}
      >
        +
      </button>{" "}
      <br />
      {count} <br />
      {refCount.current}
      {/* count는 버튼을 누를 때마다 +1 이 되어 화면에 계속 보여지는 반면 */}
      <br />
      <h2>1. useRef</h2>
      <button
        onClick={() => {
          nickName.current = "사오정"; // ref 값 변경
          console.log(nickName); // {current: 사오정}
        }}
      >
        ref 변경하기
      </button>
      {nickName.current}
      {/* 아무리 ref 변경하기 버튼을 눌러도 바뀌지 않음 */}
      <br />
      <h2> 2. 화면이 mount 될 때마다 자동포커싱 기능</h2>
      <input ref={inputRef}></input>
    </>
  );
}

 

export default App;