`useRef`와`createRef`의 차이점은 무엇입니까?


120

나는 우연히 발견했을 때 후크 문서를 살펴보고 있었다 useRef.

그들의 예를 보면…

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    // `current` points to the mounted text input element
    inputEl.current.focus();
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}

useRef로 대체 될 수있는 것 같습니다 createRef.

function TextInputWithFocusButton() {
  const inputRef = createRef(); // what's the diff?
  const onButtonClick = () => {
    // `current` points to the mounted text input element
    inputRef.current.focus();
  };
  return (
    <>
      <input ref={inputRef} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}

심판에 대한 후크가 필요한 이유는 무엇입니까? 왜 useRef존재합니까?

답변:


153

차이점은 createRef항상 새 참조를 생성 한다는 것입니다. 클래스 기반 구성 요소에서 일반적으로 구성 중에 인스턴스 속성에 ref를 넣습니다 (예 :) this.input = createRef(). 함수 구성 요소에는이 옵션이 없습니다. useRef초기 렌더링에서와 같이 매번 동일한 참조를 반환합니다.

다음은이 두 함수의 동작 차이를 보여주는 예제 앱입니다.

import React, { useRef, createRef, useState } from "react";
import ReactDOM from "react-dom";

function App() {
  const [renderIndex, setRenderIndex] = useState(1);
  const refFromUseRef = useRef();
  const refFromCreateRef = createRef();
  if (!refFromUseRef.current) {
    refFromUseRef.current = renderIndex;
  }
  if (!refFromCreateRef.current) {
    refFromCreateRef.current = renderIndex;
  }
  return (
    <div className="App">
      Current render index: {renderIndex}
      <br />
      First render index remembered within refFromUseRef.current:
      {refFromUseRef.current}
      <br />
      First render index unsuccessfully remembered within
      refFromCreateRef.current:
      {refFromCreateRef.current}
      <br />
      <button onClick={() => setRenderIndex(prev => prev + 1)}>
        Cause re-render
      </button>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

1rvwnj71x3 편집


38

createRef항상 새 참조를 반환하며 일반적으로 클래스 구성 요소의 인스턴스에 필드로 저장합니다. 기능 구성 요소의 인스턴스를 렌더링 할 때마다 동일한 참조useRef반환 합니다 . 이것은 명시 적으로 어디에도 저장하지 않더라도 ref의 상태가 렌더 사이에 지속되도록 허용하는 것입니다.

두 번째 예에서는 렌더링 할 때마다 ref가 다시 생성됩니다.


이것은 정확하지 않습니다. 귀하의 진술을 뒷받침 할 참조가 있습니까?
Adeel Imran 2019

1
이것이 어떻게 작동하는지 설명하는 React 개발자 중 한 명이 여기에 댓글을 달았습니다. reddit.com/r/reactjs/comments/a2pt15/… 이 답변에 대해 무엇이 잘못되었다고 생각하는지 알고 싶습니다.
Joe Clay

이 질문에 답하기 전에 링크를 보았습니다. 공유 한 링크에서이 사실을 어디에 표시합니까? 찾을 수 없습니까? :)
Adeel Imran

1
내가 공유 한 링크 useRef는 React 개발자 중 한 명이 게시 한의 단순화 된 구현을 보여줍니다 . 그것은 단순히 호출과 동일하지 않습니다 createRef로서, createRef후크하지 않고 통화 사이의 상태를 유지하지 않습니다. Ryan Cogswell의 답변에는 차이점에 대한 좋은 예가 있습니다.
Joe Clay

1
그 맥락에서 내 이해는 useRef가 내부에서 createRef를 사용하는 사용자 지정 후크라는 것을 추론했습니다. 지식을 공유해 주셔서 감사합니다.
Adeel Imran 2019

13

tldr

A ref는 일반 JS 객체 { current: <some value> }입니다.

React.createRef()공장은 ref { current: null }- no magic을 반환합니다 .

useRef(initValue)또한 심판 반환 { current: initValue }에 가깝다 React.createRef(). 게다가 , 이 ref는 함수 구성 요소의 여러 렌더링에 걸쳐 지속되도록 메모 합니다 .

React.createRefref 객체가 인스턴스 변수에 할당 되므로 클래스 구성 요소에서 사용하는 것으로 충분 하므로 구성 요소와 해당 수명주기 전체에서 액세스 할 수 있습니다.
this.myRef = React.createRef(); // stores ref in "mutable" this context (class)

useRef(null)기본적으로 1 과 동일합니다 .useState(React.createRef())[0]


1 교체 useRefuseState+createRef

다음 트윗 은 나를 위해 깨달았습니다.

useRef()기본적으로 useState({current: initialValue })[0]입니다.

tldr섹션의 통찰력을 통해 이제 다음과 같은 결론을 내릴 수 있습니다.

useRef(null)기본적으로 useState(React.createRef())[0]입니다.

위의 코드 useState는에서 반환 된 참조를 유지하기 위해 "남용" 합니다 React.createRef(). [0]값 부분을 선택하기 만하면 useState- [1]세터가됩니다.

useState와 달리 다시 렌더링합니다 useRef. 좀 더 공식적으로 React는 useStatesetter 메서드를 통해 새 값이 설정 될 때 의 이전 및 새 객체 참조를 비교합니다 . 우리는 경우 돌연변이 의 상태를 useState직접 그 행동이 더 많거나 적게되고, (세터 호출에 반대하지 않음) 상당useRef다시 렌더링에는 더 이상 트리거로 :

// Example of mutaing object contained in useState directly
const [ref] = useState({ current: null })
ref.current = 42; // doesn't cause re-render

참고 :이 작업을 수행하지 마십시오! useRef바퀴를 재발 명하는 대신 최적화 된 API를 사용하십시오 . 위는 설명을위한 것입니다.


3

목적을 강조하기 위해 :

createRef간단합니다 return {current: null}. ref=가장 현대적인 방식으로 소품 을 처리하는 방법 이며 그게 전부입니다 (문자열 기반은 마술과 콜백 기반이 너무 장황 해 보입니다).

useRef렌더링 전에 일부 데이터를 유지하고 변경해도 다시 렌더링되지 않습니다 useState. 그들은 거의 관련이 없습니다. 클래스 기반 구성 요소에 대해 기대하는 모든 것은 인스턴스 필드 ( this.* =) 로 이동하여 useRef함수 구성 요소에서 구현할 후보처럼 보입니다 .

말은 useCallback경계 클래스 메소드로 작동 ( this.handleClick = .....bind(this)) 재 구현 될 수있다 (하지만 우리는 안 확실히 바퀴를 다시 발명)과를 useRef.

또 다른 예로는 DOM 참조, 시간 초과 / 간격 ID, 타사 라이브러리의 식별자 또는 참조가 있습니다.

PS 나는 React 팀 useRefcreateRef. 어쩌면 useAndKeep또는 심지어 usePermanent.


1

다른 사람의 답변에 대한 또 다른 중요한 추가 사항입니다.

에 대한 새 값을 설정할 수 없습니다 createRef. 하지만 useRef.

const ur = useRef();
const cr = createRef();

ur.current = 10; // you can do it, and value is set
cr.current = 10; // you can, but it's no good, it will not change it

ref는 일반 객체이므로 current평소와 같이 속성을 변경할 수 있습니다 . 심판을 통해 생성되는 경우, 상관 없어 useRefcreateRef.
ford04
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.