React@16.x(12)ref 转发-forwardRef

1,介绍

上篇文章中提到,ref 只能对类组件使用,不能对函数组件使用。

ref 转发可以对函数组件实现类似的功能。

使用举例

import React, { Component } from "react";

function CompA(props, ref) {
    return (
        <h1>
            <div ref={ref}>组件A</div>
            <span>{props.desc}</span>
        </h1>
    );
}

const NewCompA = React.forwardRef(CompA);

export default class App extends Component {
    refA = React.createRef();

    componentDidMount() {
        console.log(this.refA);
    }

    render() {
        return <NewCompA ref={this.refA} desc="测试"></NewCompA>;
    }
}

打印结果

在这里插入图片描述

解释

通过 React.forwardRef() 来实现 ref 转发。其实就是通过 HOC:参数为组件,返回新组件。

特点:

  • 参数只能是函数组件,并且该函数接收2个参数
    • 参数一不变,依旧是 props
    • 参数二就是一个 ref: {current: null},也就是 React.forwardRef() 返回的新组件接收的 ref 属性。它让使用者来决定作为谁的引用。比如上面的例子中,就作为一个子元素的引用。
  • 返回的新组件,和原来的函数组件没有任何区别,只是可以传递 ref 属性了。

2,类组件如何使用

既然明确规定了 React.forwardRef() 的参数只能是函数,该函数的参数也是确定的,那可以将类组件包装一层来达到目的。

更改上面的例子如下:

class CompA extends Component {
    render() {
        return (
            <h1>
                <div ref={this.props.forwardRef}>组件A</div>
                <span>{this.props.desc}</span>
            </h1>
        );
    }
}

// forwardRef 这个属性名是随意的,只是约定俗成为这个单词了。
const NewCompA = React.forwardRef((props, ref) => {
    return <CompA {...props} forwardRef={ref}></CompA>;
});

4,应用场景-高阶组件HOC

在之前的高阶组件HOC中,有个问题没有解决:

const Alog = withLog(CompA)

此时使用的是 Alog 组件,那如何获取原组件 CompA 的方法和属性呢?
Alog 使用 ref 获取的并不是是 CompA 的组件实例。

可以使用 ref 转发解决:

源代码:

export default function withLog(Comp) {
    return class LogWrapper extends Component {
        componentDidMount() {
            console.log(`${Comp.name}组件被创建了`);
        }
        componentWillUnmount() {
            console.log(`${Comp.name}组件被销毁了`);
        }
        render() {
            return <Comp {...this.props} />;
        }
    };
}

修改后:

import React, { Component } from "react";

export default function withLog(Comp) {
    class LogWrapper extends Component {
        componentDidMount() {
            console.log(`${Comp.name}组件被创建了`);
        }
        componentWillUnmount() {
            console.log(`${Comp.name}组件被销毁了`);
        }
        render() {
            const { forwardRef, ...rest } = this.props;
            return <Comp ref={forwardRef} {...rest} />;
        }
    }
    return React.forwardRef((props, ref) => {
        return <LogWrapper {...props} forwardRef={ref}></LogWrapper>;
    });
}

这样在使用 withLog 时,并不会影响对源组件 ref 的获取。


以上。

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

下雪天的夏风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值