携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第21天,点击查看活动详情
什么是 ref
Refs 对元素、值的引用,例如 DOM 节点、Javascript 值等。要在功能组件中创建 ref,我们使用 useRef() 钩子返回一个可变对象,该对象的 current 属性为我们传递的初始值 useRef(initValue)。
我们在函数式组件中使用它们来创建引用。
const ref = useRef(null); // ref => { current: null }
此返回的对象将在组件的整个生命周期内持续存在。
使用
import React, { useRef } from 'react';
const BaseRef = () => {
const inputRef = useRef<HTMLInputElement>(null);
const onClick = () => {
console.log(inputRef.current?.value);
}
const onClickFocus = () => {
inputRef.current?.focus();
}
return (
<div>
<input ref={inputRef} />
<button onClick={onClick}>value</button>
<button onClick={onClickFocus}>focus</button>
</div>
);
};
useRef(null) 最初返回一个对象:{ current: null }
设置了 null 作为初始值。将它关联到 , 及其 ref 属性之后,我们可以通过 ref 定义属性类型,使用 .current 访问它
这样,当单击第一个按钮时,我们打印值,点击第二个按钮时,我们从元素中调用 focus() 方法。
因为在这个项目中我使用了 Typescript,所以我们设置 ref 的类型。我们将其定义为 HTMLInputElement 并使用可选链接 (?.) 来防止在访问 ref 的属性时出错。
回调Ref
这是 React 设置 refs 的另一种方式。useRef()传递一个函数,而不是传递由创建的 ref 属性。从官方文档可以看到,该函数接收 React 组件实例或 HTML DOM 元素作为其参数,可以在其他地方存储和访问。
查看有什么区别
const BaseRef = () => {
let inputRef: HTMLInputElement | null;
const onClick = () => {
console.log(inputRef?.value);
}
const onFocusClick = () => {
inputRef?.focus();
}
return (
<div>
<input ref={node => { inputRef = node; }} />
<button onClick={onClick}>value</button>
<button onClick={onFocusClick}>focus</button>
</div>
);
};
我们只需在函数组件中设置 ref 属性,而不是使用 useRef。
该函数接收 DOM node 并将其分配之前声明的 inputRef。我们没有使用 useRef 设置 ref,因此inputRef变量存储了 DOM 元素本身,因此我们不需要访问该.current属性。
使用 Typescript,将类型设置为 HTMLInputElement | null。
访问动态添加的DOM元素
虽然 useRef() hook 能够满足我们对 ref 所需的大多数常用场景。
但是callback ref模式为我们提供了一种更强大的方式来控制动态添加或删除子项的情况,没有与父级相同的生命周期,或者您需要在安装引用时执行任何效果。
当一个 input 动态显示之后,设置focus
import React, { useState, useRef } from 'react';
const CallbackRefDynamic = () => {
const inputRef = useRef<HTMLInputElement>(null);
const secRef = useRef<HTMLInputElement>(null);
const [visible, setVisibility] = useState(false);
const onClick = () => {
setVisibility(true);
}
const onFocusClick = () => {
inputRef.current?.focus();
}
const callbackRef = (node: HTMLInputElement) => {
console.log(node);
if(node) {
node.focus();
}
}
return (
<div>
<input ref={inputRef} />
<button onClick={onClick}>a input</button>
{visible && (
<>
<input ref={callbackRef} />
<button onClick={onFocusClick}>focus</button>
</>
)}
</div>
);
};
useRef 更改时不会通知更新,改变 .current 属性不会导致重新渲染。
因此,要在 React 将 ref 指向 input,我们需要使用 callbackRef。
总结
useRef 返回一个可变 ref 对象,其当前属性初始化为传递的参数 (initialValue)。返回的对象将在组件的整个生命周期内持续存在。它返回一个可变对象并且不会导致组件重新渲染。