Ric*_*ler 39 javascript reactjs react-hooks
当我偶然发现时,我正在浏览钩子文档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>
</>
);
}
Run Code Online (Sandbox Code Playgroud)
......好像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>
</>
);
}
Run Code Online (Sandbox Code Playgroud)
为什么我需要一个钩子来参考?为什么useRef存在?
Rya*_*ell 58
不同之处在于createRef始终会创建一个新的参考.在基于类的组件中,通常在构造期间将ref放在实例属性中(例如this.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);
Run Code Online (Sandbox Code Playgroud)
for*_*d04 39
Aref是一个普通的 JS 对象{ current: <some value> }。
React.createRef()是一家返回 ref 的工厂{ current: null }-不涉及魔法。
useRef(initValue)还返回一个{ current: initValue }类似于React.createRef(). 此外,它记住此 ref 以便在函数组件中的多个渲染中保持持久性。
React.createRef在类组件中
使用就足够了,因为 ref 对象被分配给一个实例变量,因此可以在整个组件及其生命周期中访问:
this.myRef = React.createRef(); // stores ref in "mutable" this context (class)
Run Code Online (Sandbox Code Playgroud)
useRef(null)基本上相当于 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. 更正式地说,useState当通过其 setter 方法设置新值时,React 会比较 的旧对象引用和新对象引用。如果我们直接改变的状态useState(与 setter 调用相反),它的行为或多或少地等同于useRef,因为不再触发重新渲染:
// Example of mutaing object contained in useState directly
const [ref] = useState({ current: null })
ref.current = 42; // doesn't cause re-render
Run Code Online (Sandbox Code Playgroud)
注意:不要这样做!使用优化的useRefAPI 而不是重新发明轮子。以上是为了说明目的。
Joe*_*lay 21
createRef总是返回一个新的引用,通常将其存储为类组件实例上的字段。在每次渲染功能组件实例时都useRef返回相同的引用。这是使ref的状态在渲染之间得以持久的原因,尽管您没有将其明确存储在任何地方。
在您的第二个示例中,将在每次渲染时重新创建参考。
只是为了突出一个目的:
createRef就像 一样简单return {current: null}。这是一种以ref=最现代的方式处理prop 的方法,就是这样(而基于字符串的方式太神奇了,基于回调的看起来太冗长了)。
useRef在渲染之前保留一些数据并且更改它不会导致重新渲染(就像useState那样)。他们很少有关联。您对基于类的组件所期望的一切都转到实例字段(this.* =)看起来像是要useRef在功能组件中实现的候选对象。
说useCallback作为有界类方法(this.handleClick = .....bind(this))可以重新实现(但我们肯定不应该重新发明轮子)useRef。
另一个示例是 DOM 引用、超时/间隔 ID、任何 3rd 方库的标识符或引用。
PS 我相信 React 团队最好为 选择不同的命名useRef以避免与createRef. 也许useAndKeep甚至usePermanent。
| 归档时间: |
|
| 查看次数: |
10954 次 |
| 最近记录: |