본문 바로가기
공식문서/리액트

어떻게 리액트 에서 리랜더링 없이 정보를 기억 시키는가? (useRef)

by Integer Essence 2023. 2. 17.

공부한걸 문서화해보자 싶어서

 

컴포넌트에서 리액트의 시스템을 벗어나는 제어가 필요한 경우 가있다. 

 

그때  돔을 조작하거나 정보를 기억시킬때 활용하는것이 useRef 다. 

 

그동안 돔을 조작할때만 useRef를 써먹었는데 오늘의 글은 useState 대신에 useRef를 사용 하여 값을 저장하여 쓰는 법에 대한 글이다.  

 

맨밑에도 적어놨지만 해당 글은 공식문서를 보면서 공부하며 작성한 글로 거의 공식문서 글과 거의 유사할 예정이다.

사실상 잡담빼면 걍 공식문서 번역글 

 

 

 

#리액트에서 리랜더링이 일어나는 과정 

 

이미 알고있다 시피 useState안에 저장된 값이 setFunction에 의해 변경되면 리랜더링이 일어난다. 

 

 

#ref의 개요 및 값 저장용도 로써의 기본적인사용 

 

일단 useRef 의 ref는 레퍼런스의 ref다 즉 ref 는 참조를 말한다. 

 

참조를 할려면 어떻게 해야될까? 참조를 할 변수를 생성하면되고 dom요소를 참조하고싶다면 참조하고싶은 요소에 ref를 붙여주면된다. 

 

 

import { useRef } from 'react'

 

임포트후 

 

const ref = useRef(초기값) 을 넣어줌으로 사용할 수 있다. 

 

 

 

 

#ref 값을 어떻게 update 시키는가

 

 

const ref = useRef(0)

ref에는 useState 처럼 inital value (초기 값)을 넣어줄수있다. 

 

그리고 ref는 다음과 같은 객체를 리턴한다

{

current:0 

}

 

ref 안의 current값을 업데이트 시킴으로 값을 변경시키면 되겠지

 

function handleClick(){
ref.current = ref.current + 1 
}

 

잡담 : 나는 그동안 ref를 돔 조작에만 활용해왔다. 그래서 공식문서에서 보여주는 이런식의 활용은 좀 신기하게 느껴졌다.

 

 

 

 

 

 

 

#ref로 값을 저장하는것과 state의 차이 

 

리랜더링 의 여부. ref의 값을 저장하는것은 리랜더링을 일으키지않는다. 

 

잡담 : 그럼 input value 들을 validation 에러 화면을 ui로 처리 하지않는 경우는 ref로 value를 받아오는 편이 랜더링을 줄일 수 있지않을까? 하고 생각해본다. 

 

 

 

 

 

 

# 활용 

 

공식문서의 예제에서는 stopwatch 를 예를 들고있다. 랜더링이 필요한 정보와 아닌정보에 따라 useState와 useRef를 나눠서 사용하는 방식으로 구현하고있는데 

 

setInterval을 cleartInterval로 지워주기위해선 알다시피 interval ID를 부여해줘야된다. 

 

intervalID는 랜덜링에 사용되지않음으로 

 

이때 Ref에 interval ID를할당한다. 

 

const intervalRef = useRef(null);



   clearInterval(intervalRef.current);
   
   intervalRef.current = setInterval(() => {
      setNow(Date.now());
    }, 10);

 

이렇게쓴다는것을 강조해서 보기 위해서 함수 전체가아니라 해당 부분만 뜯어왔다. 

 

 

 

 

#ref와 state의 차이 

 

 

Ref state
리랜더링을 발생시키지않는다 setState 함수로 리랜더링을 발생시킨다.
변할수있다 (mutable) -> 렌더링 프로세스 밖에서 값에 접근하고 수정하고 업데이트를 할 수있다.  불변성의 속성을 가진다 - >  useState를 쓰는게아니면 외부에서 건드릴 수 없다. 
렌더링 하는 동안 에 값을 읽을수없다 언제든지 상태값을 읽을수있다 하지만  각 렌더링에는 각자의 스냅샷을 가지고있음 (새로고침 하면 날라감)
ref.current를 리턴한다 current value와 setter 함수를 리턴한다.

ex) 

 

버튼을 누를때마다 ref 값을 증가시키고 

 

button 안에 보여지는 text를  ref  값으로 준다면 current의 값은  계속 올라가지만 text에는 변동이없다. 

 

 

 

#Deep Dive

 

딥다이브의 내용에는 useRef의 안 이 어떻게 동작하는지에 대해서 다루고있다.

 

원칙적으로는 useRef 안에 useState를 구현해서 쓸 수 있다. 

 

// Inside of React
function useRef(initialValue) {
  const [ref, unused] = useState({ current: initialValue });
  return ref;
}

이렇게 사용할것에 대한 의문을 누군가는 품고산다는것인가..

 

여기서 setRef 로 가야될 것이 unused 로 적혀있는것을 볼 수있다. 저렇게 사용하면 set함수는 불필요해진다. 

useRef는 언제나 같은 ref 객체를 반환해야되기때문에 불필요해짐

 

이렇게 되면 setter 가 없는 일반적인 상태변수라고 생각하면된다.  

객체지향 프로그래밍에 익숙하다면 this.st 대신 st.current 로 조작하면된다 (st = something)

 

# ref의 사용시기 

 

timeOutId 저장 

돔 조작

jsx 계산에 불필요한데 저장해야되는 다른 기타 오브젝트 

 

 

 

 

 

해당글은 리액트의 공식문서https://beta.reactjs.org/learn/referencing-values-with-refs를 참조하여 작성하였습니다