React高階組件中使用React.forwardRef的技巧

以前使用React.forwardRef始終沒法應用於React高階組件中,最近終於搗鼓出來了,因而記錄下來。
關鍵點就是React.forwardRef的API中ref必須指向dom元素而不是React組件。codepen實例請劃到底部。react

1、React.forwardRef使用示例app

下面就是應用到React組件的錯誤示例:dom

const  A=React.forwardRef((props,ref)=><B {...props} ref={ref}/>)

這就是我以前常常犯的錯誤, 這裏的ref是沒法生效的。函數

前面提到ref必須指向dom元素,那麼正確方法就應用而生:this

const  A=React.forwardRef((props,ref)=>(
<div ref={ref}>
<B {...props} />
</div>
))

2、React.forwardRef應用到高階組件中
2.1. withComponent類型的高階組件【1】code

import React from 'react'
import A from './a.jsx'
import PropTypes from 'prop-types';

function withA(Component){
    const ForWardedComponent = React.forwardRef((props, ref) => <div ref={ref}>
               <Component {...props} />
           </div>);
     class MidComponent extends React.Component {
        render() {
            const props = this.props
            return (
                <A {...props}>
                  <ForWardedComponent  ref={props.forwardedRef} {...props}/>
            </A>
            )
        }
    }
    
    //對MidComponent組件屬性進行類型經查 
    MidComponent.propTypes = {
        forwardedRef: PropTypes.object,
    }
    return  MidComponent
}
exports.withA=withA

這樣,在上述示例的組件A中,A的週期componentDidMount() 調用 this.props.forwardedRef.current ,指向的就是上述示例中ForWardedComponent對應的dom元素。
是B組件對應的dom的父元素,而不是該dom
在a.jsx中某處:component

componentDidMount(){
     console.log(this.props.forwardedRef.current)
    }

最後應用實例:jsx

import React from 'react'
import ReactDOM from  'react-dom'
//假設withA存儲於withA.js文件。
import {withA}   from  './withA.js'  
 const B=()=><h2>hello world</h2>
const B2=withA(B)
class App extends React.Component {
      constructor(props) {
        super(props)
        this.forwardedRef=React.creactRef()        
        }
        
        render() {
           return  <div>
               <B2  forwardedRef={this.forwardedRef}/>
           </div>
        }
}

ReactDOM.render(<App/>,document.getElementById('app'))

2.2 純粹的高階組件(Parent-Child)
【1】中並非React組件,只是一個React組件爲參數的函數,調用之後才成爲React組件。那麼直接寫入一個Parent組件又該如何呢?get

import React from 'react'
import A from './a.jsx'
import PropTypes from 'prop-types';

function AasParent(props){
    const ForWardedComponent = React.forwardRef((props, ref) => <div ref={ref}>
               {props.children}
           </div>);
      return (
                <A {...props}>
                  <ForWardedComponent  ref={props.forwardedRef} {...props}/>
            </A>)
}
AasParent.propTypes = {
        forwardedRef: PropTypes.object,
    }
 
module.exports=AasParent

最後應用實例:it

import React from 'react'
import ReactDOM from  'react-dom'
//假設AasParent存儲於AasParent.jsx文件。注意與【1】中的區別
import AasParent   from  './AasParent.jsx'  
 const B=(props)=><h2>{props.greetings}</h2>

class App extends React.Component {
      constructor(props) {
        super(props)
        this.forwardedRef=React.creactRef()        
        }
        
        render() {
           return  <AasParent forwardedRef={this.forwardedRef}>
               <B2  greetings="你好,Melo"/>
           </AasParent>
        }
}

ReactDOM.render(<App/>,document.getElementById('app'))

3、總結
1.React.forwardRef的API中ref必須指向dom元素而不是React組件。
2.在【1】的組件A中,A的週期componentDidMount() 調用 this.props.forwardedRef.current ,指向的就是【1】中ForWardedComponent對應的dom元素。是【1】中B組件對應的dom的父dom元素,而不是該dom。
3.codepen實例

相關文章
相關標籤/搜索