一 在DOM组件中使用
import React, { Component } from 'react'; // 跳转引用对象本身并不关心ref,而是由渲染函数转发ref const FancyButton = React.forwardRef((props, ref) => ( <button ref={ref} className="FancyButton"> {props.children} </button> )); class App extends Component { constructor(props) { super(props); this.myRef = React.createRef(); } click() { this.myRef.current.focus(); console.log(this.myRef.current.innerHTML) } render() { return ( <div> <FancyButton ref={this.myRef}>光彩夺目的按钮</FancyButton> <div onClick={this.click.bind(this)}>点击我</div> </div> ); } } export default App;
二 在高阶组件中使用
1 app.js
import React, { Component } from 'react'; import FancyButton from './fancyButton.jsx'; class App extends Component { constructor(props) { super(props); this.btnRef = React.createRef(); // 创建引用对象 } click(){ this.btnRef.current.print(); } render() { return ( <div> <FancyButton ref={this.btnRef} /> <div onClick={this.click.bind(this)}>点击</div> </div> ); } } export default App;
2 logProps.js
import React from 'react'; export default function logProps(Component) { // 高阶组件 class LogProps extends React.Component { componentDidUpdate(prevProps) { console.log('old props:', prevProps); console.log('new props:', this.props); } render() { const { myForwardRef, ...rest } = this.props; // 引用对象的current属性指向被包裹组件 return <Component ref={myForwardRef} {...rest} />; } } // 将高阶组件包裹在跳转引用对象中。 return React.forwardRef((props, ref) => { // 将ref属性转换成高阶组件的自定义属性,将引用对象转移到了高阶组件的props属性中。 // 防止React自动处理组件的ref属性。 return <LogProps {...props} myForwardRef={ref} />; }); }
3 fancyButton.js
import React, { Component } from 'react'; import logProps from './logProps.jsx'; class FancyButton extends Component { print(){ console.log('色彩夺目的按钮'); } render() { return <button>色彩夺目的按钮</button> } } export default logProps(FancyButton);
三 原理
1 React.forwardRef函数,只是创建一个跳转引用对象。
2 跳转引用对象(对象)也可以用作JSX语法的标签名,作用与组件(类)类似。但主要作用是提供渲染函数,转发props和ref。
3 React会在合适的时机,自动调用跳转引用对象的render方法,获取ReactElement。