나의 주니어 개발 일기/REACT

[REACT] useRef로 컴포넌트 변수 생성하기

추억을 백앤드하자 2025. 6. 27. 15:02
728x90
반응형
SMALL

useRef로 컴포넌트 변수 생성하기

useState

  • State를 생성
  • 컴포넌트 내부의 변수로 활용 가능
  • 값이 변경되면 컴포넌트 리렌더링

useRef

  • Reference 객체를 생성
  • 컴포넌트 내부의 변수로 활용 가능
  • 어떤 경우에도 리렌더링을 유발하지 않음

컴포넌트 내부에서 랜더링에 영향을 미치치 않아야 되는 변수를 생성할 때 활용할 수 있다.


아래와 같이 사용하면 전체 Register 컴포넌트에 영향을 안주면서 오직 refObj만 렌더링 된다.

결과는 Register 랜더링은 최초 한번만 되고, 오로지 refObj값만 변경된다.

const Register = () => {
    const [input, setInput] = useState({
      name : "",
      birth : "",
      country : "",
      bio : ""
    });

    const refObj = useRef(0);
    console.log("Register 랜더링");

    const onChange = () => {
        setInput({
          ...input,
          [e.target.name]: e.target.value,
        })
    }

    return(
        <div>

        <button onClick={() => {
          refObj.current++;
          console.log(refObj.current);
        }} />

          <div>
            <input
              name="name" 
              value={input.name}
              onChange={onChange} 
              placeholder={"이름"}
            />
          </div>
          ...
          ...

useRef를 사용해서 focus 해보기

const Register = () => {
    const [input, setInput] = useState({
      name : "",
      birth : "",
      country : "",
      bio : ""
    });

    const inputRef = useRef(0);

     const onSubmit= () => {
      if(input.name === ""){
        //이름을 입력하는 DOM 요소에 포커스
        console.log(inputRef.current);
        inputRef.current.focus();
      }
    };

     return(
        <div>
          <div>
            <input
              ref={inputRef}
              name="name" 
              value={input.name}
              onChange={onChange} 
              placeholder={"이름"}
            />
          </div>
           ... 

           <button onClick={onSubmit}>제출</button>  
         </div>
                 );
}

이름 값이 없을때 focus가 된다.


간단한 회원가입 폼 만들기

Register.jsx

import { useState, useRef } from "react";


//간단한 회원가입 폼
//1. 이름
//2. 생년월일
//3. 국적
//4. 자기소개
const Register = () => {
    const [input, setInput] = useState({
      name : "",
      birth : "",
      country : "",
      bio : ""
    });

    const refObj = useRef(0);
    const inputRef = useRef(0);

    const onChange = (e) => {
      refObj.current++;
      console.log(refObj.current);

        setInput({
          ...input,
          [e.target.name]: e.target.value,
        })
    }

    const onSubmit= () => {
      if(input.name === ""){
        //이름을 입력하는 DOM 요소에 포커스
        console.log(inputRef.current);
        inputRef.current.focus();
      }
    };

    return(
        <div>
          <div>
            <input
              ref={inputRef}
              name="name" 
              value={input.name}
              onChange={onChange} 
              placeholder={"이름"}
            />
          </div>

          <div>
            <input
              name="birth" 
              value={input.birth}
              onChange={onChange} 
              type="date"/>
          </div>

          <div>
            <select 
              name="country"
              value={input.country}
              onChange={onChange}>
              <option ></option>
              <option value="kr">한국</option>
              <option>미국</option>
              <option>일본</option>
            </select>
          </div>

          <div>
            <textarea 
              name="bio"
              value={input.bio}
              onChange={onChange}/>
          </div>

          <button onClick={onSubmit}>제출</button>
        </div>
    );
}

export default Register;

App.jsx

import "./App.css";

import { useState } from "react";
import Register from './components/Register';
function App() {

  return (    
    <>
    <Register />
    </>
    );
  }

export default App;


궁금증

굳이 useRef, useState를 사용하지 않고 변수 값을 컴포넌트 외부에서 선언할 수도 있다.

그러나 치명적인 문제가 존재한다.

변수값 count를 컴포넌트 외부로 빼고 변경을 시킨다.

Register.jsx

let count = 0;

//간단한 회원가입 폼
//1. 이름
//2. 생년월일
//3. 국적
//4. 자기소개
const Register = () => {
    const [input, setInput] = useState({
      name : "",
      birth : "",
      country : "",
      bio : ""
    });

    const refObj = useRef(0);
    const inputRef = useRef(0);


    const onChange = (e) => {
      count++;
      console.log("컴포넌트 밖에 변수", count);
      refObj.current++;
      console.log(refObj.current);
       ... 
       ...

App.jsx

import "./App.css";

import { useState } from "react";
import Register from './components/Register';
function App() {

  return (    
    <>
    <Register />
    <Register />
    </>
    );
  }

export default App;

그리고 Register 컴포넌트를 2번호출 했을때 문제가 발생한다.

Register 가 2번 호출되었지만 내부의 상태값들은 각각 관리되어야 하지만 컴포넌트 외부에 선언된 변수는 공유가 된다.

이러한 문제 때문에 변화될 수 있는 값은 왠만해서는 useState 또는 useRef를 사용하는것이 보다 안정적이고 권장되는 방식이다.

 

728x90
반응형
LIST