[React] Ref

youngseo·2022년 5월 18일
0

REACT

목록 보기
15/52
post-thumbnail

ref 기본

1. Ref와 DOM

react공식문서

Ref는 render 메서드에서 생성된 DOM 노드나 React 엘리먼트에 접근하는 방법을 제공합니다.

그렇다면 어떤 경우 Ref를 사용할까요?

Ref를 사용해야 할 때

  • 포커스, 텍스트 선택영역, 혹은 미디어의 재생을 관리할 때.
    • ex) 결제페이지 중 휴대번호, 주소와 같은 필수정보를 입력하지 않고 결제하기 버튼을 누른경우 작성되지 않는 폼에 포커스를 하는 경우
  • 애니메이션을 직접적으로 실행시킬 때.
  • 서드 파티 DOM 라이브러리를 React와 같이 사용할 때.

Ref 포커스 실습

import React, { useRef } from "react"

export default function UnControlledForm() {
  const inputRef = useRef()

  const handleSubmit = (e) => {
    e.preventDefault();
    alert(inputRef.current.value)
    ✅inputRef.current.focus()
    //alert을 띄운 후 focus가 되도록 작성
  }

  console.log(inputRef)

  return (
    <form onSubmit={handleSubmit}>
      <label>닉네임 :</label>
      <input type="text" name="nickname" ref={inputRef}/>
      <input type="submit" value="제출" />
    </form>
  )
}


알람창이 뜬 후 포커스가 유지되는 것을 확인할 수 있습니다.

Ref생성하기

Ref는 React.createRef()를 통해 생성되고 ref 어트리뷰트를 통해 React 엘리먼트에 부착됩니다. 보통, 컴포넌트의 인스턴스가 생성될 때 Ref를 프로퍼티로서 추가하고, 그럼으로서 컴포넌트의 인스턴스의 어느 곳에서도 Ref에 접근할 수 있게 합니다.

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }
  render() {
    return <div ref={this.myRef} />;
  }
}

Ref에 접근하기

render 메서드 안에서 ref가 엘리먼트에게 전달되었을 때, 그 노드를 향한 참조는 ref의 current 어트리뷰트에 담기게 됩니다.

const node = this.myRef.current;
ref의 값은 노드의 유형에 따라 다릅니다.

  • ref 어트리뷰트가 HTML 엘리먼트에 쓰였다면, 생성자에서 React.createRef()로 생성된 ref는 자신을 전달받은 DOM 엘리먼트를 current 프로퍼티의 값으로서 받습니다.
  • ref 어트리뷰트가 커스텀 클래스 컴포넌트에 쓰였다면, ref 객체는 마운트된 컴포넌트의 인스턴스를 current 프로퍼티의 값으로서 받습니다.
  • 함수 컴포넌트는 인스턴스가 없기 때문에 함수 컴포넌트에 ref 어트리뷰트를 사용할 수 없습니다.

CatParent

import React from "react";
import Cat from "./Cat";
//Cat안에 있는 이미지 사이즈를 알고 싶다.
export default function CatParent() {
  console.log("부모 컴포넌트 CatParent");

  return (
    <div>
      <h4> 고양이가 세상을 구한다 ️</h4>
      <div>
        <Cat />
      </div>
    </div>
  );
}

Cat

import React from "react";

const Cat = () => {
  console.log("자식 컴포넌트 Cat");

  return (
    <div>
      <img
        src="https://static01.nyt.com/images/2016/03/30/universal/ko/well_cat-korean/well_cat-superJumbo-v2.jpg?quality=90&auto=webp"
        alt="cat"
        style={{ width: "150px" }}
      ></img>
    </div>
  );
};

export default Cat;

forwardRef

부모 컴포넌트에게 DOM ref 공개하기

보기 드문 경우지만, 부모 컴포넌트에서 자식 컴포넌트의 DOM 노드에 접근하려 하는 경우도 있습니다. 자식 컴포넌트의 DOM 노드에 접근하는 것은 컴포넌트의 캡슐화를 파괴하기 떄문에 권장되지 않습니다. 그렇지만 가끔가다 자식 컴포넌트의 DOM 노드를 포커스하는 일이나, 크기 또는 위치를 계산하는 일 등을 할 때에는 효과적인 방법이 될 수 있습니다.

React 16.3 이후 버전의 React를 사용하신다면 위와 같은 경우에서 ref 전달하기(ref forwarding)을 사용하는 것이 권장됩니다. Ref 전달하기는 컴포넌트가 자식 컴포넌트의 ref를 자신의 ref로서 외부에 노출시키게 합니다. 자식 컴포넌트의 DOM 노드를 부모 컴포넌트에게 공개하는 방법에 대한 자세한 예시는 ref 넘겨주기 문서에서 볼 수 있습니다.

forwardRef실습

CatParent에서 Cat에 있는 이미지에 직접 접근하는 것이 목적입니다.

CatParent.js

import React, { useRef } from "react"; //(1)
import Cat from "./Cat";

export default function CatParent() {
  console.log("부모 컴포넌트 CatParent");
    const catRef = useRef() //(1)

  return (
    <div>
      <h4> 고양이가 세상을 구한다 ️</h4>
      <div>
        <Cat a={"a"}  ref={catRef} />  //(2)
      </div>
    </div>
  );
}

Cat.js

import React, { forwardRef } from "react"; //(2)

const Cat = ((props, ref) => {
  console.log("자식 컴포넌트 Cat");

  return (
    <div>
      <img
        src="https://static01.nyt.com/images/2016/03/30/universal/ko/well_cat-korean/well_cat-superJumbo-v2.jpg?quality=90&auto=webp"
        alt="cat"
        style={{ width: "150px" }}
        ref={ref} //(3)
      ></img>
    </div>
  );
});

export default Cat;
  1. ref를 cat에 넘겨줘야하기 때문에, CatParent에서 ref객체를 하나 만듭니다.
  2. ref={catRef}로 사용을 할 수 있습니다. 단, props와 차이점은 props는 a.a이런식으로 가져올 수 있지만 자식컴포넌트에서 ref를 받으려면 forwardref라는 것이 필요합니다.
  3. 괄호를 통해 영역을 감싸줍니다.
  4. cat에서 ref가 업데이트 되어도 부모 컴포넌트에서는 알지 못합니다.
import React, { useRef } from "react";
import Cat from "./Cat";

export default function CatParent() {
  const catRef = useRef()
  console.log("부모 컴포넌트 CatParent");
  console.log(catRef)
  return (
    <div>
      <h4> 고양이가 세상을 구한다 ️</h4>
      <div>
        <Cat a={"a"} ref={catRef} />
        <button onClick={() => alert(catRef.current.height)}>고양이의 크기를 알고 싶어</button>
      </div>
    </div>
  );
}
import React, { forwardRef } from "react";

const Cat = forwardRef((props, ref) => {
  console.log("자식 컴포넌트 Cat");
  console.log(ref)

  return (
    <div>
      <img
        src="https://static01.nyt.com/images/2016/03/30/universal/ko/well_cat-korean/well_cat-superJumbo-v2.jpg?quality=90&auto=webp"
        alt="cat"
        style={{ width: "150px" }}
        ref={ref}
      ></img>
    </div>
  );
})
export default Cat;

useRef

react공식문서-useref

const refContainer = useRef(initialValue);

useRef는 .current 프로퍼티로 전달된 인자(initialValue)로 초기화된 변경 가능한 ref 객체를 반환합니다. 반환된 객체는 컴포넌트의 전 생애주기를 통해 유지될 것입니다.

0개의 댓글