当我偶然发现useRef
时,我正在浏览hooks文档。
看看他们的例子……
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>
</>
);
}
为什么我需要一个refs的钩子?为什么useRef
存在?
7条答案
按热度按时间uklbhaso1#
不同之处在于
createRef
总是会创建一个新的ref。在基于类的组件中,你通常会在构造过程中将ref放在一个示例属性中(例如this.input = createRef()
)。在函数组件中你没有这个选项。useRef
负责每次返回与初始渲染相同的ref。下面是一个示例应用程序,演示了这两个函数的行为差异:
uqcuzwp82#
tldr
ref
是一个普通的JS对象{ current: <some value> }
。React.createRef()
是一个返回ref{ current: null }
的工厂-不涉及任何魔法。useRef(initValue)
也返回一个ref{ current: initValue }
,类似于React.createRef()
。此外,它将此ref存储为持久化,并在 function component 中跨多个渲染。在类组件中使用
React.createRef
就足够了,因为ref对象被分配给一个示例变量,因此可以在整个组件及其生命周期中访问:useRef(null)
基本上是is equivalent touseState(React.createRef())[0]
1。1将
useRef
替换为useState
+createRef
tweet对我来说很有启发:
useRef()
基本上是useState({current: initialValue })[0]
。从
tldr
部分的见解,我们现在可以进一步得出结论:useRef(null)
基本上是useState(React.createRef())[0]
。上面的代码“滥用”
useState
来持久化React.createRef()
返回的ref。[0]
只是选择useState
的值部分-[1]
将是setter。与
useRef
相比,useState
会导致重新渲染。更正式地说,当通过setter方法设置新值时,React会比较useState
的新旧对象引用。如果我们直接 mutateuseState
的状态(与setter调用相反),它的行为或多或少变得 * 等效 *useRef
,因为不再触发重新渲染:注意:不要这样做!使用优化的
useRef
API,而不是重新发明轮子。上面是为了说明目的。dly7yett3#
createRef
总是返回一个新的ref,你通常会将其存储为类组件示例上的一个字段。useRef
在函数组件示例的每次渲染时都会返回 * 相同的ref*。这就是为什么ref的状态可以在渲染之间保持不变,尽管你没有显式地将其存储在任何地方。在第二个示例中,将在每次渲染时重新创建参照。
cidc1ykv4#
只是为了强调一个目的:
createRef
和return {current: null}
一样简单。这是一种以最现代的方式处理ref=
prop的方法,仅此而已(而基于字符串的方法太神奇了,基于回调的方法看起来太冗长了)。useRef
在渲染之前保留一些数据,并且更改它不会导致重新渲染(就像useState
一样)。它们很少相关。您对基于类的组件的所有期望都转到示例字段(this.* =
)看起来像是在功能组件中使用useRef
实现的候选者。假设
useCallback
作为有界类方法(this.handleClick = .....bind(this)
)工作,并且可以用useRef
重新实现(但我们不应该肯定地重新发明轮子)。另一示例是DOM引用、超时/间隔ID、任何第三方库的标识符或引用。
PS我认为React团队最好为
useRef
选择不同的命名,以避免与createRef
混淆。可能是useAndKeep
甚至usePermanent
。kmpatx3s5#
ref是一个普通的JS对象{ current:}.
wd2eg0qa6#
useRef和forwardRef在React中是两个不同的东西,有不同的用例。
另一方面:
rqdpfwrv7#
另一个重要的补充,其他的答案。
您不能为
createRef
设置新值,但可以为useRef
设置新值。