React

useRef는 무엇인가?.araboja

잼굴 2022. 12. 13. 20:48

(R.ef 아님ㅋㅋ)

언제 쓰나? 

 

1. 렌더링을 발생시키지 말아야하는 값을 다룰때 편리하다

어떤 값을 저장하는 저장공간으로 사용된다.

State의 변화 -> 렌더링 -> 컴포넌트 내부 변수들 초기화됨. 원하지 않는 랜더링이 될때가있다.

Ref가 변화하면 렌더링이 일어나지 않아서 변수들의 값이 유지된다.

State의 변화가 일어나서 렌덜이이 되어도 Ref의 값은 유지된다.

 

2. Ref를 통해서 Dom요소에 접근할수있다. 

 


일단 제일 중요한건

Ref는 렌더링 되지않는다이다.

 

간단하게 카운트 버튼으로 설명해 본다

import React, { useState, useRef } from 'react'
import '../Pages/test.css'

const Test = () => {
    const [count,setCount] = useState(0);
    const countRef = useRef(0);
    console.log("countRef",countRef);
    console.log("렌더링...")
    const increaseCount = () => {
        setCount(count+1)
    }
    const increaseCountRef = () => {
        countRef.current = countRef.current +1;
    }
  return (
    <div className="black">
    <div>State: {count}</div>
    <p>Ref: {countRef.current}</p>
    <button onClick={increaseCount}>State 올려</button>
    <button onClick={increaseCountRef}>Ref올려</button>
    </div>
  )
}

export default Test

State올려 클릭1번

첫 화면 렌더링 -> 버튼 클릭 State 변화 -> 렌더링  렌더링이 총 2회 되었다.

 

Ref올려&nbsp; 클릭 1번

Ref올려를 한번 클릭했는데 값이 바뀌지않고, 콘솔값도 안바뀐다.

-> 렌더링하지 않았기때문에 !!

 

다시 State올려를 눌려서 렌더링을 한다면?

 

Ref의 값이 바뀌었다. 저 안에선 이미 값이 바뀌어 있었는데 렌더링을 안해줘서 표가 안났을뿐이다.

Ref올려 함수 속에 콘솔을 찍는다면 

 

클릭마다 콘솔이 찍힌다

콘솔이 찍힌다.

 

여기서 Ref의 장점은?  자주 바뀌는값이 있다면 계속 렌더링 해줘야하기 때문에 성능이 떨어진다.

 

 

 


기존 변수들이랑 비교해보자

import React, { useState, useRef } from 'react'
import '../Pages/test.css'

const Test = () => {
  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);
  };
  const printResults = () => {
    console.log(`ref: ${countRef.current}, var: ${countVar}`)
  }

  return (
    <div className='black'>
      <p>Ref: {countRef.current}</p>
      <p>Var: {countVar}</p>
      <button onClick={doRendering}>렌더링 하기</button>
      <button onClick={increaseRef}>Ref 올려</button>
      <button onClick={increaseVar}>Var 올려</button>
      <button onClick={printResults}>Ref Var 값 출력</button>
    </div>
  )
}

export default Test

Ref올려 3번, Var올려 3번을 누르고 렌더링을 시켰을땐 

Var는 숫자가 올라가지 않았다.

그리고 다시 Ref올려를 누르면 4부터 시작된다.

 

왜? -> 기존 변수는 렌더링하면 초기화 되기때문, Ref는 저장돼있기 때문

 

 


 

import { render } from '@testing-library/react';
import React, { useState, useRef } from 'react'
import { useEffect } from 'react';
import '../Pages/test.css'

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

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

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

export default Test

Ref는 리렌더링을 발생시키지 않아서 무한루프에 빠지지 않는다.

 

 


 

useRef를 통해서 Dom요소에 접근하기

 

미션: Input 요소를 클릭 하지않아도 focus되게 해보자

import React from 'react'
import { useEffect } from 'react';
import { useRef } from 'react'

const Test = () => {
  const inputRef = useRef();
  useEffect(()=>{
    console.log(inputRef);
  }, [])

  return (
    <div>
      <input type="text" placeholder="username"/>
      <button>로그인</button>

    </div>
  )
}

export default Test

아직 Ref안에 값이 없기때문에 Ref가 뭔지 콘솔 찍어서 확인해 봐도 undefinded라고 나온다.

 

      <input ref={inputRef} type="text" placeholder="username"/>

input에 ref를 넣으니  current값에 input이 들어간다

 

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

이제 이렇게 해주면 화면이 렌더링되고나서 Input창을 클릭하지 않아도 foucs가 되어있을것이다.

 

 

 

로그인 버튼을 누르면 Ref값을 보여주고 다시 Input을 focus하게 해보자.

login이라는 함수를 만들자!

import React from 'react'
import { useEffect } from 'react';
import { useRef } from 'react'

const Test = () => {
  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 Test

 

 

 

 

쉽죠잉~~~~~~~~?