2015-06-15 48 views
3

假設我有一個關於汽車銷售的數據集,並且我正在構建顯示可顯示數據不同方面的圖表的組件。如何解決這個問題,使用組合而不是React中的mixin?

例如,一個組件可以顯示年份汽車的平均銷售價格,而另一個組件可以顯示汽缸數量與去年購買汽車的里程數量的關係。

這些組件還可以進一步參數化,以便它們僅顯示在特定國家購買的汽車的數據等。似乎使用道具來傳遞參數和數據似乎是適當的,以便可以使用這些組件像這樣:

<MileageByCylinder country="US" year="2014" dataset={data} /> 
<AvgSellingPricesByYear country="US" dataset={data} /> 

到目前爲止,這麼好。但是,讓我們說,我構建了兩個視圖(頁面),這些視圖組成了不同的組件。第一個將靜態顯示不同國家的年份銷售價格,而另一個將有一個用於選擇國家的UI,並且還顯示每缸的里程數。兩個視圖都需要以某種方式獲取它們傳遞給圖表組件的數據集。但是如何重新獲取數據集的邏輯呢?

隨着混入,這是可以做到如下:

var CarDataMixin = { 

    componentDidMount: { 
    // fetch car data and 
    // call this.setState({carData: fetchedData}), 
    // once data has been (asynchronously) fetched 
    } 

} 

var FirstView = React.createClass({ 

    mixins: [CarDataMixin], 

    render: function() { 
    return (
     <div> 
      <AvgSellingPricesByYear country="US" dataset={this.state.carData} /> 
      <AvgSellingPricesByYear country="UK" dataset={this.state.carData} /> 
      <AvgSellingPricesByYear country="FI" dataset={this.state.carData} /> 
     </div> 
    ) 
    } 

}) 

var SecondView = React.createClass({ 

    mixins: [CarDataMixin], 

    handleNewCountry: function(country) { 
    this.state{country: country} 
    }, 

    render: function() { 
    return (
     <div> 
      <CountryChooser onChange={this.handleNewCountry} /> 
      <MileageByCylinder country="{country}" year="2014" dataset={this.state.carData} /> 
      <AvgSellingPricesByYear country="{country}" dataset={this.state.carData} /> 
     </div> 
    ) 
    } 

}) 

不錯,真不錯。但是很多人建議不要使用mixin,而應該使用該組合。解決這個使用組成我想出的唯一辦法如下:

  1. 請即通過其狀態爲孩子當道具根組件:

    var CarSalesRoot = React.createClass({ 
        componentDidMount: { 
         // fetch car data and 
         // call this.setState({carData: fetchedData}), 
         // once data has been (asynchronously) fetched 
        } 
    
        renderChildren: function() { 
         return React.Children.map(this.props.children, function (child) { 
          return React.addons.cloneWithProps(child, { 
           carData: this.state.carData 
          }) 
         }.bind(this)) 
        }, 
    
    
        render: function() { 
         return <div>{this.renderChildren()}</div> 
        } 
    }); 
    
  2. 創建無視圖混入:

    var FirstView = React.createClass({ 
        render: function() { 
         return (
          <div> 
          <AvgSellingPricesByYear country="US" dataset={this.props.carData} /> 
          <AvgSellingPricesByYear country="UK" dataset={this.props.carData} /> 
          <AvgSellingPricesByYear country="FI" dataset={this.props.carData} /> 
          </div> 
         ) 
        } 
    }); 
    
  3. 創建它包裝既根組件和主視圖分量的包裝部件:

    var FirstViewMain = React.createClass({ 
        render: function() { 
         return (
          <CarSalesRoot> 
          <FirstView /> 
          </CarSalesRoot> 
         ) 
        } 
    }); 
    

這樣感覺有點棘手,並且使數據流動更不明確。我覺得這是非常基本的東西,應該以一種乾淨的方式解決。我錯過了明顯的東西嗎?或者這實際上是一種習慣和乾淨的解決方案?

回答

6

使用組合的另一種選擇是創建一個「高階組件」,它類似於函數式編程中的高階函數,但實際上它只是一個包裝,它只是您呈現的代碼的輕微變化。

  1. 定義高次成分:

    var bindToCarData = function (Component) { 
        return React.createClass({ 
        componentDidMount: { 
         // fetch car data and 
         // call this.setState({carData: fetchedData}), 
         // once data has been (asynchronously) fetched 
        }, 
    
        render: function() { 
         return <Component carData={ this.state.carData } /> 
        } 
        }); 
    }); 
    
  2. 然後換你的組件時,你定義它。

    var FirstView = bindToCarData(React.createClass({ 
        render: function() { 
        return (
         <div> 
          <AvgSellingPricesByYear country="US" dataset={this.props.carData} /> 
          <AvgSellingPricesByYear country="UK" dataset={this.props.carData} /> 
          <AvgSellingPricesByYear country="FI" dataset={this.props.carData} /> 
         </div> 
        ) 
        } 
    })); 
    

這節省你寫(在你的問題中的3)額外的組件,它在數據流的邏輯直接在需要數據的組件的關係。

如果需要,可以將其他參數傳遞給bindToCarData函數。

+0

謝謝!這已經看起來更好了。這種做法可能是要走的路。 –

+2

我也會推薦'...... this.props'在高級組件的'component'渲染上傳播,這樣任何分配給包裝版本的道具都會收到它們。 – max

+0

是,最大。這在大多數情況下是可取的。 –