React Hooks之useRef、createRef、forwardRef
一 Ref(reference)引用:用于直接使用dom元素的某个方法,或者直接使用自定义组件中的某个方法。处理对象:管理焦点,文本选择,媒体播放(媒体回放);触发动画;集成第三方的DOM库。
- 作用于内置的html组件,得到的是真实的dom
- ref作用于类组件,得到的是类的实例
- ref不能作用于函数组件
- Ref不推荐字符串方式,一般是函数或者对象方式引用。
import React, { Component, createRef } from 'react';
export default class Test extends Component {
constructor(props){
super(props)
this.createRefTxt = createRef()
}
handleFnClick = () => {
console.log(this.fnTxt);
this.fnTxt.focus();
};
handleObjectClick = () => {
console.log(this.createRefTxt);
this.createRefTxt.current.focus();
};
render () {
return (
<>
<div className="func-way">
<input
ref={(el) => { this.fnTxt = el; }}
type='text'
/>
<button onClick={this.handleFnClick}>函数方式</button>
</div>
<div className="object-way">
<input
ref={this.createRefTxt}
type='text'
/>
<button onClick={this.handleObjectClick}>对象方式</button>
</div>
</>
);
}
}
二 useRef、createRef、forwardRef区别:
1 useRef:
一般用于函数组件
useRef 不仅仅是用来管理 DOM ref 的,它还相当于 this , 可以存放任何变量。
当 useRef 的内容发生变化时,它不会通知您。更改.current属性不会导致组件重新渲染。因为他一直是一个引用 。
2 createRef:
一般用于类组件,React.createRef 创建一个能够通过 ref 属性附加到 React 元素的 ref。
如果用于函数组件中,当App这个函数组件被重新渲染时,App函数将会执行,并且重新创建、初始化所有的变量和表达式。因此,createRef每次都会被执行,所以对应的值总是为null。
createRef 每次渲染都会返回一个新的引用,而 useRef 每次都会返回相同的引用。
3 forwardRef:
Ref 转发是一个可选特性,其允许某些组件接收 ref,并将其向下传递(换句话说,“转发”它)给子组件。
import React, { Component } from 'react'
function A(props, ref){
console.log(props, ref)
return <h1 ref={ref}>A组件</h1>
}
// 传递函数组件,得到一个新的组件,不能传递类组件,并且函数组件必须使用第二个
const NewA = React.forwardRef(A)
export default class Test extends Component {
ARef = React.createRef()
componentDidMount() {
console.log(this.ARef) // {current: h1}
}
render() {
return (
<div>
<NewA ref={this.ARef} words="sdfsd"/>
</div>
)
}
}
4 父组件调用子组件方法:
import React, { Component, createRef } from 'react';
class CustomTextInput extends Component {
constructor(props) {
super(props);
this.focus = this.focus.bind(this);
}
focus () {
// Explicitly focus the text input using the raw DOM API
this.textInput.focus();
}
handleChild = () => {
console.log('父组件调用子组件方法')
}
render () {
// Use the `ref` callback to store a reference to the text input DOM
// element in an instance field (for example, this.textInput).
return (
<div>
<input
type="text"
ref={(input) => { this.textInput = input; }} />
{/* //此时input参数就是表示该DOM本身 */}
<input
type="button"
value="Focus the text input"
onClick={this.focus}
/>
</div>
);
}
}
export default class Test extends Component {
componentDidMount () {
console.log(this.textInput);
//父组件自动调用子组件CustomTextInput实例的focus方法
this.textInput.focus();
}
handleClick = () => {
this.textInput.handleChild();
}
render () {
return (
<div>
<CustomTextInput
ref={(input) => { this.textInput = input; }} />
<button onClick={this.handleClick}>父组件按钮</button>
</div>
);
}
}
三 useRef与createRef更新:useRef与createRef更新区别
能够获取上一次值的原因:由于 useEffect 在 Render 完毕后才执行,因此 ref 的值在当前 Render 中永远是上一次 Render 时候的,我们可以利用它拿到上一次 Props
import React, { useState, createRef, useRef, useEffect } from 'react';
const Child1 = () => {
const [count, setCount] = useState(0);
const preCountUserRef = useRef();
console.log(count);
useEffect(() => {
preCountUserRef.current = count;
});
return (
<div>
<p>preCount:{preCountUserRef.current}</p>
<p>You clicked {count} times</p>
<button onClick={() => { setCount(count + 1) }}>Click me</button>
</div>
)
}
export default Child1

浙公网安备 33010602011771号