保存变量, 改变不引起渲染
js
import { useRef} from 'react';
const dataRef = useRef(null)
...
dataRef.current = setTimeout(()=>console.log('...'),1000)
绑定dom
js
const inputRef = useRef(null)
<input ref = {inputRef} />
绑定dom列表 - ref 回调
js
const itemsRef = useRef({})
{catList.map(cat => (
<li
key={cat.id}
ref={(node) => {
const map = getMap();
if (node) {
itemsRef.current[cat.id] = node;
} else {
delete itemsRef.current[cat.id]
}
}}
>
{cat.id}
</li>
))}
访问子组件属性
将 ref 放在自定义组件上,默认情况下会得到 null。因为默认情况下,React 不允许组件访问其他组件的 DOM 节点。手动操作另一个组件的 DOM 节点会使你的代码更加脆弱。
想要暴露其 DOM 节点的组件必须选择该行为。一个组件可以指定将它的 ref "转发"给一个子组件。
js
// 父组件
const inputRef = useRef(null);
<MyInput ref={inputRef} /> // 1. 告诉 React 将对应的 DOM 节点放入 inputRef.current 中。但是这取决于 MyInput 组件是否允许,默认不允许。
// 子组件 MyInput
import { forwardRef } from 'react';
const MyInput = forwardRef((props, ref) => { // 2. forwardRef 接受父组件的 inputRef 作为第二个参数 ref 传入组件,第一个参数是 props。
return (
<input {...props} ref={ref} /> // 3. 将 ref 传递给 <input>
)
});
使用 useImperativeHandle 暴露 API
js
import { forwardRef, useRef, useImperativeHandle } from 'react';
const MyInput = forwardRef((props, ref) => {
const realInputRef = useRef(null);
useImperativeHandle(ref, () => ({
// 只暴露 focus,没有别的
focus() {
realInputRef.current.focus();
},
}));
return <input {...props} ref={realInputRef} />;
});
export default function Form() {
const inputRef = useRef(null);
function handleClick() {
inputRef.current.focus();
}
return (
<>
<MyInput ref={inputRef} />
<button onClick={handleClick}>
聚焦输入框
</button>
</>
);
}