提高React component重用性:Composition

這陣子寫React的components,常常很快就完成了期待的效果。
但是總覺得沒有重用性、無法從application獨立出來。

我想將元件中可重用的部份獨立出來,成為基本元件,接著針對application另寫元件去擴充這些基本元件。
有辦法讓一個component去繼承另一個component嗎?似乎不行。

我首先在開發React-Lightbox時遇到了上述問題。

我想製作一個Lightbox效果的plugin,提供Lightbox、LightboxTrigger、LightboxModal三個component,讓developer自訂觸發Lightbox的按鈕、Lightbox框框內的內容。

用法類似這樣:

        React.renderComponent(
            
                
                    
                
                
                    
                
            ,                
            document.getElementById('react-canvas')
        );

範例中的ToggleButton跟MyPanel是由developer自訂。

該怎麼達成這個效果呢?

毫無頭緒之下,我寫出像這樣的code:

        for (j in this.props){
            if (j !== 'children'){
                this.props.children.props[j] = this.props[j];                
            }
        }
        for(i in this.props.children){
            this.props.children[i].props.openLightbox = this.openLightbox;
            this.props.children[i].props.closeLightbox = this.closeLightbox;
            this.props.children[i].props.setLightboxState = this.setLightboxState;
            for (j in this.state){
                this.props.children[i].props[j] = this.state[j];                
            }
        }

簡單地說,就是硬著頭皮傳遞某些props、達到類似「繼承」的「擴充」效果。

眼前的問題解決了,但是tomchentw指出這樣寫法的問題所在(感謝指點):

‘At my first glance it looks pretty magic.’

該怎麼辦呢?

我最後終於在這篇SO的問答找到了一線希望:

Extending React.js components

由component去wrap住基本component來達到擴充的效果,然後利用JSX Spread Attributes的幫助來傳遞props。

利用這些,我開發出了第二個React的plugin:Tag Manager

所謂「使用者自訂component去擴充基本component」的code,大概長這樣:

/** @jsx React.DOM */

var MyCustomTagManager = React.createClass({

    addTagCallback: function(tagName, setStateCallback){
        alert('Add a tag! Maybe you should send an ajax!');
        setStateCallback({id: 99, name: tagName});
    },

    removeTagCallback: function(tag){
        alert('Remove a tag! Maybe you should send an ajax!');
    },

    render: function(){
        return(
            
        )
    }

});            

反省

再看一眼,發現前面的寫法跟後面的寫法其實都是「用component去包住component」,意義上其實類似。
(都是叫composition?我理論沒學好,對專有名詞不熟@@”)

後面的寫法看起來更explicit了,maintainability跟readability應該也更高了吧?
您覺得呢?