React元件中對子元件children進行加強

tornoda發表於2019-06-23

React元件中對子元件children進行加強

問題

如何對元件的children進行加強,如:新增屬性、繫結事件,而不是使用<div>{this.props.children}</div><div>上進行處理。

前車之鑑

今天寫元件遇到這個問題,在網上查閱了很多資料,都說可以使用React.cloneElement進行處理,但是結果並不是預期想要的。

先看看這個東西有什麼用:

React.cloneElement(element, [props], [...childrn])

根據React官網的說法,以上程式碼等價於:

<element.type {...element.props} {...props}>{children}</element.type>

這麼做其實也是給children包了一層標籤,再對其進行間接處理,沒有直接修改children

如:

// App.jsx
<Father>
    <div style={{ color: 'red' }} onClick={() => console.log('hello')}>
        demo
    </div>
<Father>

我們希望在Father.jsx的內部將div轉為inline-block。按照網上的做法,是這樣的:

// Father.jsx
const Son = React.cloneElement(
    this.props.children,
    {
        style: {
            display: 'inline-block'
        }
    }
)

但是實際效果是這樣的:

<div style={{ dispaly: 'inline-block' }}>
    <div style={{ color: 'red' }} onClick={() => console.log('hello')}>
        demo
    </div>
<div>

哈!?子元素的父元素被設為了inline-block,和我們想要的<div>demo</div>被設為inline-block。結果與預期完全不同,簡直大失所望!!!

React.clone根本對不起它clone的名字!!!

自我探索

思路: jsx語法表示的元素只是react元件的一個語法糖。所以元件是物件。既然是物件我們就可以直接對其進行修改。

嘗試在控制檯列印一個如下react元件:

// this.props.children
console.log(
    <div
        style={{ color: 'red' }}
        onClick={() => {
            console.log('hello');
        }}
    >
        demo
    </div>
);

如下:

React元件中對子元件children進行加強

所以直接修改this.props.children即可:

// Father.jsx
const { children } = this.props;
const Son = {
    ...children,
    props: {
            ...children.props,
        dispaly: {
            ...children.style,
            display: 'inline-block'
        },
        onTransitionEnd: () => { console.log('hello world') }
    }
}

總結

如何對元件的children進行直接加強,直接修改this.props.children物件即可。

相關文章