본문 바로가기
카테고리 없음

React Ref

by kicksky 2021. 2. 11.

보통, 원래, 일반적인 경우:

- 부모와 자식 컴포넌트가 있을 때, 자식 컴포넌트를 수정하려면 부모 컴포넌트에서 새로운 props를 전달하여 자식을 리렌더링함

특수한 경우:

- 그런 과정 안 거치고 직접 자식을 수정하고 싶음

- 컴포넌트 인스턴스( 클래스로 선언된 컴포넌트, this 키워드로 참조되는 대상 ), DOM 엘리먼트

쓰기 전 경고:

- state에 어디에 있어야 할지 먼저 고민해야 함


생성:

- 컴포넌트의 인스턴스 생성할 때, Ref를 프로퍼티로 추가 → 인스턴스 내부에서 자유롭게 접근 가능

접근:

- render 메서드 안에서 ref가 엘리먼트에 ref attribute 통해 전달되면 해당 노드에 대한 참조가 ref.current에 담김

- ref의 값

  • HTML 엘리먼트에 쓰인 경우 - ref는 자신을 전달받은 DOM 엘리먼트를 current 프로퍼티의 값으로 받음

    • 컴포넌트 마운트 할 때, current 프로퍼티에 DOM 엘리먼트 대입 - 해제될 때, current 프로퍼티는 다시 null로

    • 이 작업은 componentDidMount 또는 componentDidUpdate 호출되기 "전"에 발생

  • 커스텀 클래스 컴포넌트에 쓰인 경우 - 마운트된 컴포넌트 인스턴스를 받음


콜백 ref:

- ref attr에 createRef( )로 생성된 ref가 아니라 "함수"를 전달함

- 이 함수의 인자로 컴포넌트 인스턴스나 DOM 엘리먼트가 옴 ( 다른 곳에서 저장되고 접근 가능 )

- DOM 노드에 ref를 덧붙이거나 떼어낼 때, 특정한 코드를 실행시키고 싶다면 사용

- 이를테면 useEffect를 안 써도 되는 것

 this.textInput = null;
 
 this.setTextInputRef = element => {
      this.textInput = element;
 }; 
 ...
 render() {
    return (
      <div>
        <input
          type="text"
          ref={this.setTextInputRef}
        />
        <input
          type="button"
          value="Focus the text input"
          onClick={this.focusTextInput}
        />
      </div>
    );
 }

- 인스턴스 마운트 → ref 콜백을 DOM 엘리먼트와 함께 호출 ( ref={this.setTextInputRef })

- 인스턴스 마운트 해제 → ref 콜백을 null과 함께 호출


useRef( 초기값 )

- .current 프로퍼티로 전달된 인자로 초기화, 변경 가능한 값을 담고 있는 "상자"

- 변경 가능한(mutable?) ref 객체; 컴포넌트 전 생애주기 내내 유지

- 렌더링을 할 때마다 동일한 ref 객체를 제공, 따라서 내용이 변경될 때 알려주지 않음

- 자식에게 명령적으로 접근하는 경우

- 순수 자바스크립트 객체를 생성하기 때문에 가변값을 유지하는 데 편리

- 값은 유지하되 굳이 리렌더링 할 필요는 없을 때


forwardRef

- ref를 자식 컴포넌트로 전달하기

- 자식 컴포넌트를 forwardRef로 감싸주면 됨

- 부모 컴포넌트는 아무것도 모름


Q. 인스턴스 변수와 같은 것이 있습니까?

'ref' 객체는 변경 가능한(mutable) current 프로퍼티를 가지며, 어떤 값이든 보유할 수 있는 일반 컨테이너. class의 인스턴스 프로퍼티와 유사. (a generic container whose current property is mutable and can hold any value, similar to an instance property on a class.)

function Timer() {
  const intervalRef = useRef();

  useEffect(() => {
    const id = setInterval(() => {
      // ...
    });
    intervalRef.current = id;
    return () => {
      clearInterval(intervalRef.current);
    };
  });
  // ...
}
 // ...
  function handleCancelClick() {
    clearInterval(intervalRef.current);
  }

id는 effect에 로컬로 존재해도 충분하기 때문에 인터벌을 세팅만 하고 싶은 거라면 ref가 불필요하다.

그러나 인터벌을 이벤트 처리로 지우고 싶을 때는 ref가 유용. handleCancelClick( )

주의: 렌더링 중에 ref 설정을 피하기. 일반적으로 이벤트 처리effect에서 ref를 수정하는 것이 좋다.


댓글