useRef、ref 和 forwardRef 的区别
React 中三种 ref 相关 API 的使用场景和区别
问题
useRef、ref 和 forwardRef 这三个 API 有什么区别?分别在什么场景下使用?
解答
useRef
useRef 是一个 Hook 函数,用于函数组件中创建可变的 ref 对象。返回的 ref 对象在组件整个生命周期内保持不变,不会因为重新渲染而改变。
function MyComponent() {
const inputRef = useRef(null);
const focusInput = () => {
inputRef.current.focus();
};
return (
<>
<input ref={inputRef} />
<button onClick={focusInput}>聚焦输入框</button>
</>
);
}
useRef 主要用于:
- 存储 DOM 元素引用
- 保存任何可变值(不会触发重新渲染)
- 替代类组件中的实例变量
ref
ref 是 React 元素的一个属性,可以在类组件和函数组件中使用。在类组件中,ref 可以直接访问组件实例。
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
}
focusInput = () => {
this.inputRef.current.focus();
};
render() {
return (
<>
<input ref={this.inputRef} />
<button onClick={this.focusInput}>聚焦输入框</button>
</>
);
}
}
forwardRef
forwardRef 用于将父组件的 ref 转发到子组件内部的 DOM 元素或组件实例。这在封装可复用组件时特别有用。
const FancyInput = React.forwardRef((props, ref) => {
return <input ref={ref} className="fancy-input" {...props} />;
});
function Parent() {
const inputRef = useRef(null);
return <FancyInput ref={inputRef} />;
}
关键点
- useRef 是 Hook,用于函数组件;createRef 用于类组件,每次渲染都会创建新实例
- useRef 返回的对象在整个生命周期内保持不变,适合存储不触发渲染的可变值
- forwardRef 用于将 ref 从父组件传递到子组件内部,解决函数组件无法直接接收 ref 的问题
- ref 本身只是一个属性,可以指向 DOM 元素、类组件实例或 useRef/createRef 创建的对象
目录