프론트앤드/React

[포스코x코딩온] 웹개발자 입문 과정 8주차 | ref

영최 2023. 4. 27. 23:43
728x90

1. ref란?

 Refenrence의 약자로,

 render 메서드에서 생성된 DOM 노드나 React 엘리먼트에 접근하는 방법이다.

 

 HTML에서 요소를 선택할 때 아래와 같이 id를 지정해서 요소를 선택하지만

<div id="id1"> 내용 </div>

 리액트의 경우 컴포넌트가 중복되면 id 또한 중복될 수 있다는 문제점이 있다.

 

 그러나 이 ref를 사용한다면 컴포넌트 내부에서만 작동되므로, 문제가 되지 않는다.

 

 즉, DOM을 직접적으로 건드려야할 때 ref를 사용한다.

 (예를 들면, input 태그에 focus를 주거나, cusor:pointer로 지정할 때)

 

 그러나 남용하기보다는 만약 state를 지정할 수 있다면 state를 사용하자. 

 그 이유는 리액트에서는 랜더링할 때 ref의 current 값을 알 수 없기 때문이다.

 

 ref의 경우 리랜더링이 필요없는 값을 보통 지정하는데 만약 그렇지 않을 경우 오류를 발생할 수 있기 때문이다.

 

 예를 들면 ref를 로컬변수로 지정해서 값을 변경한다고 한다면, 랜더링되어도 값이 그대로 유지되므로 ref값을 변경시킨다한들  컴포넌트는 랜더링 되지 않는다.  (아래 함수형 컴포넌트의 두번째 예제 참고)

 

 정리하자면 아래와 같다.

  • 전역적으로 작동하지 않고 컴포넌트 내부에서 선언 및 사용됨
  • 동일한 컴포넌트를 반복해서 사용해도 각 컴포넌트 내부에서만 동작됨(중복 X)
  • DOM을 직접적으로 건드려야할 때 사용됨
  • 리랜더링이 필요하지 않은 값을 지정함

 

 클래스 형 컴포넌트의 경우 별도의 import 없이 사용가능하다.

 

 클래스 형 컴포넌트 사용 방법 -1 : ref 콜백함수 작성 및 props로 전달

<input ref={(ref) => { this.myInput = ref;}}/>

 클래스 형 컴포넌트 사용 방법 -2 : 내장 함수 createRef 객체 사용

myInput = React.createRef();
...
<input type="text" ref={this.myInput} />

 

 그러나 함수형의 경우 useRef를 import해야하며,

 사용 방법은 아래와 같다.

import { useRef } from "react";
...
const inputRef = useRef();
...
<input type="text" ref={inputRef} />
<button onClick={()=>{inputRef.current.focus()}}>버튼</button>

 각각의 경우에 대해서 아래 예제를 통해 자세히 알아보도록 한다.

 

2. 함수형 컴포넌트에서의 Ref

 

 가. 예제 1

 

예제1 결과

  함수형 컴포넌트에서  ref를 이용하여 버튼 클릭 시 input에 focusing 및 disabled하는 

  실습 코드를 작성하면 아래와 같다.

import { useRef } from "react";
const RefSample1 = () => {
  //1. ref 객체 만들기
  const inputRef = useRef();
  const handleFocus = () => {
    //3. userRef() 만든 객체의 current 값으로 접근
    //console.log(inputRef); //{current: input}
    //console.log(inputRef.current); //<input type="text">

    //input에 focus 주기
    //focus(): 지정된 html요소에 포커스 설정
    inputRef.current.focus();
  };
  const handleDisabled = () => {
    inputRef.current.disabled = true;
  };
  return (
    <>
      <p>함수형 컴포넌트에서 버튼 클릭시 input focusing</p>
      {/* 2. 직접 접근해야하는 DOM요소에 ref prop을 설정 */}
      <input type="text" ref={inputRef} />
      <button onClick={handleFocus}>focus</button>
      <button onClick={handleDisabled}>disabled</button>
    </>
  );
};

export default RefSample1;

  

  •   import { useRef } from "react";  함수형 컴포넌트이므로 useRef를 import한다.
  • const inputRef = useRef(); useRef()객체를 생성해서 inputRef변수에 담는다.
  • <input ... ref={inputRef} /> input 태그에 ref로 inputRef변수를 지정한다.
  • <button onClick={()=>inputRef.current.focus()}>focus</button>  focus버튼 클릭 시 inputRef.current값인 input태그에 focus()로 focus를 지정해준다. 
  • <button onClick={()=>inputRef.current.disabled = true}>disabled</button> disabled 버튼 클릭시 disabled 속성을 true로 지정해서 input태그 내 입력을 막는다.

 

 나. 예제 2

 

예제 2 결과

 

  함수형 컴포넌트에서  ref를 변수로 이용하여 plus ref 버튼 클릭 시 값이 증가 , 

  minus ref 버튼 클릭시 값이 감소 하는 실습 코드를 작성하면 아래와 같다.

 

//로컬변수로 사용하는 건 그렇게 많이 쓰이지는 않음, 거의 없음
//내부적으로만 변경할 때 사용

import { useRef } from "react";
const RefSample2 = () => {
  //1.useRef()를 이용해서 로컬 변수 만들기
  const id = useRef(1);
  // console.log(id); //{current: 1}
  const plusId = () => {
    //id값 중가
    id.current += 1;
    //콘솔 찍기
    console.log(id.current);
  };
  const minusId = () => {
    //id값 중가
    id.current -= 1;
    //콘솔 찍기
    console.log(id.current);
  };
  return (
    <>
      {/* 값이 변하지 않음, 로컬변수-값이 변해도 렌더링 되지 않음 */}
      <h1>{id.current}</h1>
      <button onClick={plusId}>plus ref</button>
      <button onClick={minusId}>minus ref</button>
    </>
  );
};

export default RefSample2;

 

  앞서 ref 정의에서 설명했듯이, ref를 로컬 변수로 지정해도 되지만,

  렌더링이되지 않으므로 값이 변해도 처음 지정한 값이 화면에 동일하게 출력된다.

 

  (앞선 실습 예제 1과 ref 지정부분이 동일하므로 코드 설명은 생략하겠다.)

 

3. 클래스형 컴포넌트에서의 Ref

 

 가. 예제 1 - ref  콜백함수 사용

 

실습 1

  클래스형 컴포넌트에서  ref를 이용하여 버튼 클릭 시 input에 focusing 되는

  실습 코드를 작성하면 아래와 같다.

//클래스형 컴포넌트 ref방법
import React from "react";
class RefSample3 extends React.Component {
  handleFocus = () => {
    // console.log(this); //현재 컴포넌트: RefSample3 {props: {…}, context: {…}, refs: {…}, updater: {…}, handleFocus: ƒ, …}
    // console.log(this.myInput.value); //input value 출력 (input 창에 입력한 값)
    this.myInput.focus();
  };
  render() {
    return (
      <>
        <p>클래스형 컴포넌트에서 버튼 클릭 시 input focusing</p>
        <input
          type="text"
          ref={(ref) => {
            this.myInput = ref;
          }}
        />
        <button onClick={this.handleFocus}>focus</button>
      </>
    );
  }
}

export default RefSample3;
  • <input ref={(ref) => { this.myInput = ref;}}/>; 사용하고자 하는 DOM요소인 input태그에 ref라는 콜백 함수를 작성 하고 props로 전달한다. 이때 ref를 컴포넌트의 멤버 변수로 설정하는데 ref는 임의로 설정 가능하다 ex) myInput
  • <button onClick={()=>(this.myInput.focus())}>focus</button> focus라는 버튼을 누르면  myInput에 focuse속성을 준다.

 

 나.예제 2 - createRef 객체 사용

 

  위처럼 DOM 요소에 ref라는 콜백함수를 지정하지 않고도 클래스형 컴포넌트에서 ref를 사용하는 방법이 있다.

  바로 클래스형 컴포넌트의 내장 함수인 createRef 객체를 사용하는 것이다.

 

  작동 결과는 위 예제 1과 동일하다.

 

  아래 예제 코드를 통해 확인해보자

//클래스형 컴포넌트 ref방법
import React from "react";
class RefSample4 extends React.Component {
  //1. createRef()로 객체 생성
  myInput = React.createRef();

  handleFocus = () => {
    //3.current 이용해서 DOM요소 접근
    console.log(this.myInput);
    this.myInput.current.focus();
  };
  render() {
    return (
      <>
        <p>클래스형 컴포넌트에서 버튼 클릭 시 input focusing</p>
        {/* 2.ref props으로 myInput 연결 */}
        <input type="text" ref={this.myInput} />
        <button onClick={this.handleFocus}>focus</button>
      </>
    );
  }
}

export default RefSample4;

 

  • myInput = React.createRef(); React.createRef 함수를 이용해 컴포넌트 내부에서 변수의 ref 요소를 담는다.
  • <input type="text" ref={this.myInput} />   실제 DOM 값인 input태그에 myInput변수를 연결해준다.
  • <button onClick={()=>(this.myInput.current.focus();)}>focus</button> 사용할 때는 this.myInput.current를 이용해서 사용한다.

 

 

이번 시간에 ref에 대해서 알아보았다.

다음 블로그 포스팅에서는 lifecycle에 대해 알아보도록 하겠다.

728x90