피리부는 사나이 (pied piper)

[React] useRef 본문

React

[React] useRef

코더 451 2022. 7. 27. 20:15

useRef : 순수 자바스크립트 객체를 생성한다

값의 접근은 refContainer.current로 할 수 있다.

const refContainer = useRef(initialValue);

 

useRef를 사용해야하는 상황 

 

  1. 렌더링 상관없이 값을 변경해야할 때 
  2. 컴포넌트 태그에 직접 접근해야할 때 리액트에선 useRef를 사용한다. 
    (바닐라 js에서는 querySelector or getElementById)

   결국에는 useRef는 렌더링 없이 접근한 태그 요소의 값을 바꿀 때 사용하는 것 

   (data, state 상관없이 component에 DOM을 제어하고 싶을 때 ref를 사용)

 

 

  단 Ref는 남발하지 않는 것이 좋다
ref 없이 구현할 수 있는지 고려 후 사용하는 것이 중요

재사용면에서 Ref는 전역이 아니라 컴포넌트 내부에서만 작동하기 때문에

 

 

   useRef를 사용하는 방식과 사용하지 않는 방식에는 어떤 차이가 있을까? 

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

function Counter() {
  const [count, setCount] = useState(0)
  const [countTwo, setCountTwo] = useState(0)
  let countThree = useRef(0)
  let countFour = 0
  console.log(countThree)

  // 랜더링 됨
  const handleCountUp = (e) => {
    setCount(count + 1)
    console.log(count) // 비동기 -> useEffect로 추적하면 동기 가능
  }
  // 랜더링 됨
  const handleCountUpTwo = (e) => {
    setCountTwo(countTwo + 1)
    console.log(countTwo) // 비동기 -> useEffect로 추적하면 동기 가능
  }
  // 클릭하면 변수의 값은 증가하지만 랜더링은 되지 않음
  const handleCountUpThree = (e) => {
    countThree.current = countThree.current + 1
    console.log(countThree.current)
  }
  // 랜더링되 안되고 다른 state가 변해서 재렌더링 되어도 0으로 초기화
  const handleCountUpFour = (e) => {
    countFour = countFour + 1
    console.log(countFour)
  }

  useEffect(() => {
    console.log('count가 감시되고 있습니다.')
    console.log(`감시된 변수 : ${count}`)
  }, [count]) // count가 변경되는 것을 감시
  return(
    <>
      <div>{count}</div>
      <button onClick={handleCountUp}>up!</button>
      <div>{countTwo}</div>
      <button onClick={handleCountUpTwo}>up!</button>
      <div>{countThree.current}</div>
      <button onClick={handleCountUpThree}>up!</button>
      <div>{countFour}</div>
      <button onClick={handleCountUpFour}>up!</button>
    </>
  )
}

function App() {
  return (
    <div>
      <Counter/>
    </div>
  );
}

export default App;

 

 

useRef를 써야해야할 때 

상황1 : 아이디 input이나 비밀번호 input의 입력이 완료되지 않은 채 로그인 버튼을 누르면 입력되지 않은 input 태그에

focus를 주고 싶다.

 

 

 

 if (emailInput.current.value === "") {
    alert("이메일을 입력해주세요");
    emailInput.current.focus();
    return; // if, else 문에 들어오게 되면 setState 실행없이 바로 return
  } else if (pwInput.current.value === "") {
    alert("비밀번호를 입력해주세요");
    pwInput.current.focus();
    return;
  }

 

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

const App = () => {
  const emailInput = useRef(null); // email input에 대한 useRef
  const pwInput = useRef(null); // pw input에 대한 useRef

  const [emailValue, setEmailValue] = useState(""); // email state 값
  const [pwValue, setPwValue] = useState(""); // pw state 값

  const inputCheck = (e) => {
    e.preventDefault();
    if (emailInput.current.value === "") {
      alert("이메일을 입력해주세요");
      emailInput.current.focus();
      return;
    } else if (pwInput.current.value === "") {
      alert("비밀번호를 입력해주세요");
      pwInput.current.focus();
      return;
    }
    setEmailValue(emailInput.current.value);
    setPwValue(pwInput.current.value);
  };

  return (
    <form style={{ display: "flex", flexDirection: "column" }}>
      <label>
        이메일 : <input type="email" ref={emailInput} />
      </label>
      <label>
        비밀번호 : <input type="password" ref={pwInput} />
      </label>

      <button type="submit" style={{ width: "100px" }} onClick={inputCheck}>
        회원가입
      </button>
      <span>{emailValue}</span>
      <span>{pwValue}</span>
    </form>
  );
};

export default App;

 

 

 

'React' 카테고리의 다른 글

[React] map으로 컴포넌트 리스트 만들기  (0) 2022.07.25
Comments