Javascript `useRef` 和 `createRef` 有什么区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/54620698/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What's the difference between `useRef` and `createRef`?
提问by Rico Kahler
I was going through the hooks documentation when I stumbled upon useRef.
当我偶然发现useRef.
Looking at their example…
看看他们的例子……
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>
</>
);
}
…it seems like useRefcan be replaced with createRef.
……好像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>
</>
);
}
Why do I need a hook for refs? Why does useRefexist?
为什么我需要一个用于 refs 的钩子?为什么useRef存在?
回答by Ryan Cogswell
The difference is that createRefwill always create a new ref. In a class-based component, you would typically put the ref in an instance property during construction (e.g. this.input = createRef()). You don't have this option in a function component. useReftakes care of returning the same ref each time as on the initial rendering.
不同之处在于它createRef总是会创建一个新的 ref。在基于类的组件中,您通常会在构造期间将 ref 放在实例属性中(例如this.input = createRef())。您在功能组件中没有此选项。useRef负责每次返回与初始渲染相同的 ref。
Here's an example app demonstrating the difference in the behavior of these two functions:
这是一个示例应用程序,演示了这两个函数的行为差异:
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);
回答by Joe Clay
createRefalways returns a new ref, which you'd generally store as a field on a class component's instance. useRefreturns the same refupon every render of a functional component's instance. This is what allows the state of the ref to persist between renders, despite you not explictly storing it anywhere.
createRef始终返回一个新的 ref,您通常会将其存储为类组件实例上的字段。在每次渲染功能组件的实例时useRef返回相同的 ref。这就是允许 ref 的状态在渲染之间保持不变的原因,尽管您没有明确地将它存储在任何地方。
In your second example, the ref would be re-created upon every render.
在您的第二个示例中,将在每次渲染时重新创建 ref。
回答by skyboyer
Just to highlight a purpose:
只是为了突出一个目的:
createRefis as simple as return {current: null}. It's a way to handle ref=prop in most modern way and that's it(while string-based is toooo way magic and callback-based looks too verboose).
createRef就像 一样简单return {current: null}。这是一种以ref=最现代的方式处理prop 的方法,就是这样(而基于字符串的方式太神奇了,基于回调的看起来太冗长了)。
useRefkeeps some data before renders and changing it does not cause re-render(as useStatedoes). They are rarely related. Everything you expect for class-based component go to instance fields(this.* =) looks like candidate to be implemented with useRefin functional components.
useRef在渲染之前保留一些数据并且更改它不会导致重新渲染(就像useState那样)。他们很少有关联。您对基于类的组件所期望的一切都转到实例字段(this.* =)看起来像是要useRef在功能组件中实现的候选对象。
Say useCallbackworks as bounded class methods(this.handleClick = .....bind(this)) and may be re-implemented(but we should not re-invent the wheel for sure) with useRef.
说useCallback作为有界类方法(this.handleClick = .....bind(this))可以重新实现(但我们肯定不应该重新发明轮子)useRef。
Another examples are DOM refs, timeout/interval IDs, any 3rd party libraries' identifiers or references.
另一个示例是 DOM 引用、超时/间隔 ID、任何 3rd 方库的标识符或引用。
PS I believe React team better chose different naming for useRefto avoid confusion with createRef. Maybe useAndKeepor even usePermanent.
PS 我相信 React 团队最好为 选择不同的命名useRef以避免与createRef. 也许useAndKeep甚至usePermanent。
回答by ford04
Following statementwas enlightening for me:
以下陈述对我很有启发:
useRef(null)is basicallyuseState(React.createRef())[0].
useRef(null)基本上是useState(React.createRef())[0]。
A refis a plain object { current: <some value> }.
Aref是一个普通对象{ current: <some value> }。
React.createRef()creates { current: null }- no magic, see the implementation.
React.createRef()创建{ current: null }- 没有魔法,请参阅实现。
useRef(initialValue)creates { current: initialValue }like React.createRef(). Besides, it memoizesthis ref to be useable across multiple renders in a function component (implementation).
useRef(initialValue)创建{ current: initialValue }像React.createRef(). 此外,它记住此 ref 以便在函数组件(implementation)中的多个渲染中可用。
Above code uses useStateto store this ref. [0]just selects the value part of useState- [1]would be the setter. Now we can mutatethe state of useStateand don't cause a re-render, similar to useRef. This is, because React compares the object reference to detect changes - which does not change here:
上面的代码用于useState存储这个引用。[0]只是选择的价值部分useState-[1]将是二传手。现在我们可以改变的状态useState并且不会导致重新渲染,类似于useRef. 这是因为 React 比较对象引用来检测变化——这里没有变化:
const [ref] = useState({ current: null })
ref.current = 42; // doesn't cause re-render (object was mutated)
Note: Don't do this, it's just for illustration!
注意:不要这样做,这只是为了说明!
In summary, use the optimized API for its intended use case:
总之,将优化的 API 用于其预期用例:
useState→ immutable state/valuesuseRef→ mutable DOM node references or stored values in function componentscreateRef→ mutable DOM node references in class components; you can use instance variables for other values
useState→ 不可变的状态/值useRef→ 函数组件中的可变 DOM 节点引用或存储值createRef→ 类组件中的可变 DOM 节点引用;您可以将实例变量用于其他值
回答by Green
Yet another but important addition to other's answers.
另一个但重要的补充其他人的答案。
You can't set a new value for createRef. But you can for useRef.
您无法为 设置新值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


