Forwarding Refs

Forwarding Refs

react中我们最开始接触到ref是在表单组件中的非受控组件,我们先来回顾一下这个

// 类 组件
class Hello extends React.Component {
    //  1、调用 React.createRef() 方法创建一个 ref 对象
    txtRef = React.createRef()

    handleClick = () => {
        // 3、通过 ref 对象获取到文本框的值
        console.log(this.txtRef.current.value)
    }
    render() {
        return (
            <div>
                {/* 2、将创建好的 ref 对象添加到文本框中 */}
                <input type="text" ref={this.txtRef} />
                <button onClick={this.handleClick}>click</button>
            </div>
        )
    }
}

这里我们在组件Hello中创建了一个ref并且把这个ref传递给了一个input,这样我们就能获取到input中的value,这里我们对 ref 只进行了一次的传递,我们可以对将 ref 进行一层层的向下传递

接下来我们以官网的例子来看看

const FancyButton = React.forwardRef((props, ref) => (
    <button ref={ref} className="FancyButton">
        {props.children}
    </button>
))

// You can now get a ref directly to the DOM button:
const ref = React.createRef()
<FancyButton ref={ref}>Click me!</FancyButton>

同样的先创建一个 ref 然后把这个 ref 作为组件的一个属性进行传递,在该组件中通过 React.forwardRef 这个方法来进行接收,这样我们就能在 React.forwardRef 内部获取到传递的 ref ,并且可以再次把这个 ref 传递个一个 react 元素或组件,最后的结果就是我们用React.createRef创建的ref现在指向的就是button这个元素了,接下来想要获取这个元素就和之前的方式一样了,使用ref.current 获取的就是对应的元素。

注意:只有在React.forwardRef中才能通过第二个参数获取到对应的 ref,在函数组件和类组件中是无法通过props获取到的。

React.forwardRef 接受一个函数作为参数,这个函数接收两个参数,一个参数是 props 另一个就是 ref ,然后会返回一个 react 节点

const reactNode = React.forwardRef((props, ref) => reactNode)

ref 在高阶组件中的使用

function logProps(WrappedComponent) {
    class LogProps extends React.Component {
        componentDidUpdate(prevProps) {
            console.log("old props:", prevProps)
            console.log("new props:", this.props)
        }

        render() {
            return <WrappedComponent {...this.props} />
        }
    }

    return LogProps
}
import FancyButton from "./FancyButton"

const ref = React.createRef()

// 我们导入的 FancyButton 组件是高阶组件(HOC)LogProps。
// 尽管渲染结果将是一样的,
// 但我们的 ref 将指向 LogProps 而不是内部的 FancyButton 组件!
// 这意味着我们不能调用例如 ref.current.focus() 这样的方法
<FancyButton label="Click Me" handleClick={handleClick} ref={ref} />

上面也说了在函数组件和类组件中是无法获取到传递的 ref 的,所以这也就导致了现在的 ref 指向的就是当前的组件,而不是高阶组件中包裹的那个组件,要解决这个问题也是简单的,这就需要我们在高阶组件内部再进行一个处理,就是通过使用上面的 React.forwardRef 来对高阶组件进行一次包裹,最终我们使用的组件其实就是 React.forwardRef 返回的。

function logProps(Component) {
    class LogProps extends React.Component {
        componentDidUpdate(prevProps) {
            console.log("old props:", prevProps)
            console.log("new props:", this.props)
        }

        render() {
            const { forwardedRef, ...rest } = this.props

            // 将自定义的 prop 属性 “forwardedRef” 定义为 ref
            return <Component ref={forwardedRef} {...rest} />
        }
    }

    // 注意 React.forwardRef 回调的第二个参数 “ref”。
    // 我们可以将其作为常规 prop 属性传递给 LogProps,例如 “forwardedRef”
    // 然后它就可以被挂载到被 LogPros 包裹的子组件上。
    return React.forwardRef((props, ref) => {
        return <LogProps {...props} forwardedRef={ref} />
    })
}

再 devTool 中显示名称

// 在 DevTools 中为该组件提供一个更有用的显示名,使用displayName。
// 例如 “ForwardRef(logProps(MyComponent))”
const name = Component.displayName || Component.name
forwardRef.displayName = `logProps(${name})`

return React.forwardRef(forwardRef)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值