나는 우연히 발견했을 때 후크 문서를 살펴보고 있었다 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
존재합니까?
답변
차이점은 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);
답변
createRef
항상 새 참조를 반환하며 일반적으로 클래스 구성 요소의 인스턴스에 필드로 저장합니다. 기능 구성 요소의 인스턴스를 렌더링 할 때마다 동일한 참조 를 useRef
반환 합니다 . 이것은 명시 적으로 어디에도 저장하지 않더라도 ref의 상태가 렌더 사이에 지속되도록 허용하는 것입니다.
두 번째 예에서는 렌더링 할 때마다 ref가 다시 생성됩니다.
답변
tldr
A ref
는 일반 JS 객체 { current: <some value> }
입니다.
React.createRef()
공장은 ref { current: null }
– no magic을 반환합니다 .
useRef(initValue)
또한 심판 반환 { current: initValue }
에 가깝다 React.createRef()
. 게다가 , 이 ref는 함수 구성 요소의 여러 렌더링에 걸쳐 지속되도록 메모 합니다 .
React.createRef
ref 객체가 인스턴스 변수에 할당 되므로 클래스 구성 요소에서
사용하는 것으로 충분 하므로 구성 요소와 해당 수명주기 전체에서 액세스 할 수 있습니다.
this.myRef = React.createRef(); // stores ref in "mutable" this context (class)
useRef(null)
기본적으로 1 과 동일합니다 .useState(React.createRef())[0]
1 교체 useRef
로 useState
+createRef
다음 트윗 은 나를 위해 깨달았습니다.
useRef()
기본적으로useState({current: initialValue })[0]
입니다.
tldr
섹션의 통찰력을 통해 이제 다음과 같은 결론을 내릴 수 있습니다.
useRef(null)
기본적으로useState(React.createRef())[0]
입니다.
위의 코드 useState
는에서 반환 된 참조를 유지하기 위해 “남용” 합니다 React.createRef()
. [0]
값 부분을 선택하기 만하면 useState
– [1]
세터가됩니다.
useState
와 달리 다시 렌더링합니다 useRef
. 좀 더 공식적으로 React는 useState
setter 메서드를 통해 새 값이 설정 될 때 의 이전 및 새 객체 참조를 비교합니다 . 우리는 경우 돌연변이 의 상태를 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를 사용하십시오 . 위는 설명을위한 것입니다.
답변
목적을 강조하기 위해 :
createRef
간단합니다 return {current: null}
. ref=
가장 현대적인 방식으로 소품 을 처리하는 방법 이며 그게 전부입니다 (문자열 기반은 마술과 콜백 기반이 너무 장황 해 보입니다).
useRef
렌더링 전에 일부 데이터를 유지하고 변경해도 다시 렌더링되지 않습니다 useState
. 그들은 거의 관련이 없습니다. 클래스 기반 구성 요소에 대해 기대하는 모든 것은 인스턴스 필드 ( this.* =
) 로 이동하여 useRef
함수 구성 요소에서 구현할 후보처럼 보입니다 .
말은 useCallback
경계 클래스 메소드로 작동 ( this.handleClick = .....bind(this)
) 재 구현 될 수있다 (하지만 우리는 안 확실히 바퀴를 다시 발명)과를 useRef
.
또 다른 예로는 DOM 참조, 시간 초과 / 간격 ID, 타사 라이브러리의 식별자 또는 참조가 있습니다.
PS 나는 React 팀 useRef
이 createRef
. 어쩌면 useAndKeep
또는 심지어 usePermanent
.
답변
다른 사람의 답변에 대한 또 다른 중요한 추가 사항입니다.
에 대한 새 값을 설정할 수 없습니다 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