본문 바로가기

React/이론공부

[React Hooks] useRef

useRef 란?

- 저장공간 또는 DOM 요소에 접근하기 위해 사용되는 react hook

Ref 은 reference (즉, 참조를 뜻함)
우리가 자바스크립트를 사용 할 때 DOM 을 선택하기 위해서 querySelector 등의 함수를 사용함
React 를 사용하는 프로젝트에서도 가끔씩 DOM 을 직접 선택해야 하는 상황이 필요함
그때 사용하는 것이 useRef

 

useRef 의 기본 구문

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

 

ref object의 구조

{ current : value }
반환된 ref 은 컴포넌트의 전 생의 주기를 통해 유지가 된다.
=> 컴포넌트가 계속해서 렌더링되어도 언마운트 되기 전까지는 값을 그대로 유지할 수 있음.

 

useRef의 이용 상황

 

저장공간

ref 는 state 와 비슷하게 어떠한 값을 저장해 두는 저장 공간으로 사용이 됨.

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

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

state의 변화 -> 렌더링 -> 그래도 ref의 값은 유지됨
변경 시 렌더링이 발생시키지 말아야 하는 값을 관리할 때 아주 유용함.

 

DOM 요소에 접근

document.querySelector 와 같이, DOM 요소에 접근할 때 사용될 수 있다. (focus 등등)

 

useRef의 장점

useRef은 리렌더링을 일으키지 않기 때문에 constant 느낌으로 관리될 만한 것들이나 instance 를 useRef 을 사용하여 생성하면 불필요한 메모리 사용을 줄일 수 있음

 

useRef 변수관리

함수는 렌더링이 될 때마다 다시 처음부터 함수가 불려와지는 것이기 때문에, 변수같은 것들이 초기화 된다.

하지만 Ref 는 함수가 아무리 렌더링되어도, 컴포넌트의 전생에 주기에 값이 저장된다.

마운트에서 언마운트가 해제될 때 까지 값을 유지할 수 있다는 뜻임.

 

Ref 와 변수의 차이점

function App() {
  const [render, setRender] = useState(0)
  const countRef = useRef(0);
  let countVar = 0;

  const doRendering = () => {
    setRender(render + 1)
  }

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

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

  return (
    <div className="App">
      <p>Ref : {countRef.current}</p>
      <p>var : {countVar}</p>

      <button onClick={doRendering}>렌더링!</button>
      <button onClick={increaseRefState}>Ref 올려</button>
      <button onClick={increaseVarState}>Var 올려</button>
    </div>
  );
}

렌더링을 한 동시에 변수 (countVar) 는 초기화되기 때문에, 0부터 다시 시작된다.
ref는 렌더링을 해도 값이 저장되어있기 때문에 , 초기화되지 않고 2부터 다시 증가하는 모습을 볼 수 있다.

 

useEffect 를 사용해 ref 관리하기

1. 안좋은 예

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

  useEffect(() => {
    console.log('렌더링')
    setRenderCount(renderCount + 1)
  })

  return (
    <div className="App">
      <div>Count : {count}</div>
      <button onClick={() => setCount(count + 1)}> count up </button>
    </div>
  );
}
count 가 업데이트 된다면, useEffect 가 불려온다.
useEffect 안에도 state 를 업데이트하는 것이 있기 때문에, 계속 렌더링된다.

 

2. 좋은 예

function App() {
  const [count, setCount] = useState(1)
  const renderRef = useRef(1)

  useEffect(() => {
    console.log("renderingCount : ", renderRef.current);
    ++renderRef.current;
  })

  return (
    <div className="App">
      <div>Count : {count}</div>
      <button onClick={() => setCount(count + 1)}> count up </button>
    </div>
  );
}
ref 는 리렌더링을 발생시키지 않으니까, 무한 렌더링이 되지 않는다.

 

useRef DOM 요소 접근

 

DOM 요소 접근 방법

      <input type="text" ref={ref} />
ref 속성으로 ref 를 넣어주면 된다.

 

DOM 요소 사용 예제

 

홈페이지가 새로고침되었을 때, input 에 focus 주기

function App() {
  const inputRef = useRef()

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

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

 

간단한 로그인 예제

function App() {
  const inputRef = useRef()

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

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

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

 

'React > 이론공부' 카테고리의 다른 글

[React Hooks] useMemo  (0) 2023.01.24
[React Hooks] useContext & Context  (0) 2023.01.24
[React Hooks] useEffect  (0) 2023.01.24
[React Hooks] useState  (0) 2023.01.20
리액트 개발 환경 설치하기  (0) 2023.01.16