String ref
实例
// string ref
class MyComponent extends React.Component {
componentDidMount() {
this.refs.myRef.focus();
}
render() {
return <input ref="myRef" />;
}
}
Callback ref
实例
// callback ref
class MyComponent extends React.Component {
componentDidMount() {
this.myRef.focus();
}
render() {
return <input ref={(ele) => {
this.myRef = ele;
}} />;
}
}React.createRef
实例
// React.createRef
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
componentDidMount() {
this.myRef.current.focus();
}
render() {
return <input ref={this.myRef} />;
}
}React.forwardRef
主要用于穿过父元素直接获取子元素的 ref
HOC 的 ref 是无法通过 props 进行传递的,因此无法直接获取被包裹组件(WrappedComponent),需要进行中转。
function HOCProps(WrappedComponent) {
class HOCComponent extends React.Component {
constructor(props) {
super(props);
this.setWrappedInstance = this.setWrappedInstance.bind(this);
}
getWrappedInstance() {
return this.wrappedInstance;
}
// 实现 ref 的访问
setWrappedInstance(ref) {
this.wrappedInstance = ref;
}
render() {
return <WrappedComponent ref={this.setWrappedInstance} {...this.props} />;
}
}
return HOCComponent;
}
const App = HOCProps(Wrap);
<App ref={(dom) => {
// 只能获取到 HOCComponent
console.log(dom);
// 通过中转后可以获取到 WrappedComponent
console.log(dom.getWrappedInstance());
}} />在拥有 forwardRef 之后,就不需要再通过 getWrappedInstance 了,利用 forwardRef 能直接穿透 HOCComponent 获取到 WrappedComponent。
function HOCProps(WrappedComponent) {
class HOCComponent extends React.Component {
render() {
const { forwardedRef, ...rest } = this.props;
return <WrappedComponent ref={forwardedRef} {...rest} />;
}
}
return React.forwardRef((props, ref) => {
return <HOCComponent forwardedRef={ref} {...props} />;
});
}
const App = HOCProps(Wrap);
<App ref={(dom) => {
// 可以直接获取 WrappedComponent
console.log(dom);
}} />useRef
const refContainer = useRef(initialValue);
useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref 对象在组件的整个生命周期内保持不变。
一个常见的用例便是命令式地访问子组件:
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
// `current` 指向已挂载到 DOM 上的文本输入元素
inputEl.current.focus();
};
return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}本质上,useRef 就像是可以在其 .current 属性中保存一个可变值的“盒子”。你应该熟悉 ref 这一种访问 DOM 的主要方式。如果你将 ref 对象以
形式传入组件,则无论该节点如何改变,React 都会将 ref 对象的 .current 属性设置为相应的 DOM 节点。
然而,useRef() 比 ref 属性更有用。它可以很方便地保存任何可变值,其类似于在 class 中使用实例字段的方式。
这是因为它创建的是一个普通 Javascript 对象。而 useRef() 和自建一个 {current: ...} 对象的唯一区别是,useRef 会在每次渲染时返回同一个 ref 对象。请记住,当 ref 对象内容发生变化时,useRef 并不会通知你。变更 .current 属性不会引发组件重新渲染。如果想要在 React 绑定或解绑 DOM 节点的 ref 时运行某些代码,则需要使用回调 ref 来实现。
然而,useRef() 比 ref 属性更有用。它可以很方便地保存任何可变值,其类似于在 class 中使用实例字段的方式。
这是因为它创建的是一个普通 Javascript 对象。而 useRef() 和自建一个 {current: ...} 对象的唯一区别是,useRef 会在每次渲染时返回同一个 ref 对象。请记住,当 ref 对象内容发生变化时,useRef 并不会通知你。变更 .current 属性不会引发组件重新渲染。如果想要在 React 绑定或解绑 DOM 节点的 ref 时运行某些代码,则需要使用回调 ref 来实现。

京公网安备 11010502036488号