我在翻阅钩子文档时偶然发现了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就像return {current: null}一样简单。这是一种以最现代的方式处理ref= prop的方法,就是这样(而基于字符串的方法太神奇了,而基于回调的方法看起来太冗长了)。
useRef在呈现前保留了一些数据,改变它不会导致重新呈现(就像useState那样)。他们之间很少有联系。对于基于类的组件,您所期望的所有内容都到实例字段(这。* =)看起来像是在功能组件中使用useRef实现的候选。
说useCallback工作作为有界类方法(这。handleClick = .....bind(this)),并且可以使用useRef重新实现(但我们肯定不应该重新发明轮子)。
另一个例子是DOM引用,超时/间隔id,任何第三方库的标识符或引用。
另外,我认为React团队最好为useRef选择不同的命名,以避免与createRef混淆。可能使用andkeep或者usePermanent。
区别在于createRef总是会创建一个新的ref。在基于类的组件中,你通常会在构造过程中将ref放在实例属性中(例如:input = createRef())。在函数组件中没有这个选项。useRef负责每次返回与初始呈现时相同的ref。
下面是一个演示这两个函数行为差异的示例应用程序:
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);