[React] 비제어컴포넌트 Ref

youngseo·2022년 7월 27일
0

REACT

목록 보기
21/52
post-thumbnail

ref 기본

react공식문서

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

그렇다면 일반적으로 어떤 경우 Ref를 사용할까요?

Ref를 사용해야 할 때

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

1. 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>
  )
}


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

2. Ref생성 및 부착하기

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

클래스 컴포넌트

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

함수 컴포넌트

function LoginRef() {
  const [inputValue, setInputValue] = useState()
  const inputRef = useRef()

  const changeHandler = () => {
    setInputValue(`${inputRef.current.value}`)
  }

  return (
    <div>
      <input
        placeholder="검색어를 입력하세요"
        ref={inputRef}
        onChange={changeHandler}
      />

      {inputValue}
    </div>
  )
}

3. ⭐재런더링이 되지 않는 효과적인 변수 만들기

useRef 는 값이 변해도, 재렌더링 되지 않는 변수를 만들고자 할 때도 사용할 수 있습니다.
useRef 값의 경우, 값이 변화하면 변화된 값을 저장은 하지만 재렌더링을 하지는 않습니다.

import React, { useRef } from 'react'

function Refs() {
  const inputRef = useRef(0)

  const keyHandler = () => {
    console.log(inputRef.current + 1)    
  } 

  return (
    <>
        <p>{inputRef.current}</p>
        <button onClick={keyHandler}>버튼!</button>
    </>
  )
}

export default Refs

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

  • 자식 컴포넌트에서 부모 컴포넌트에서 전달한 ref를 받기 위해서는 forwardRef라는 것이 필요합니다.
import React, { forwardRef } from "react"; //(2)

const Cat = forwardRef((props, ref) => { //forwardRef()로 감싸줍니다.
  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;

0개의 댓글