2016-07-10 46 views
1

這是我想要實現的。我有兩個React組件ProductProductInfoPanel,顯示在ProductList組件內。 Product顯示有關產品的選定信息,例如產品名稱和價格。單擊產品時,更多詳細信息將顯示在ProductInfoPanel中。所以我需要通過wah twas點擊到ProductInfoPanel反應:從渲染方法外部更新組件的道具而不使用狀態

這是我目前如何將它們連接在一起。每個Product獲得一個傳入的點擊處理程序,當被調用時它將回傳product對象,然後傳遞到ProductInfoPanel的道具。 ProductList使用狀態來跟蹤點擊的內容,因此當它發生變化時,會觸發信息面板的重新渲染。

class ProductList extends React.Component { 
    render() { 
    return (
     <div> 

     <div className='content'> 

      <ul> 
      { this.props.products.map((product, index) => { 
       return (
       <li key={index}> 
        <Product product={product} 
        clickHandler={this.onProductClicked.bind(this)}/> 
       </li> 
      ); 
      })} 
      </ul> 

     </div> 

     <div className='side-panel'> 
      <ProductInfoPanel product={this.state.selectedProduct} /> 
     </div> 

     </div> 
    ); 
    } 

    onProductClicked(clickedProduct) { 
     // Use the product object that was clicked, and updates the state. 
     // This updates the info panel content. 
     this.setState({ selectedProduct: clickedProduct }); 
    } 

} 

這裏大概是如何構造這兩個組件。

class Product extends React.Component { 
    render() { 
    // Even though it needs only name and price, it gets the whole product 
    // object passed in so that it can pass it to the info panel in the 
    // click handler. 
    return (
     <div onClick={this.onClicked.bind(this)}> 
     <span>{this.props.product.name}</span> 
     <span>{this.props.product.price}</span> 
     </div> 
    ); 
    } 

    onClicked(e) { 
    this.props.clickHandler(this.props.product); 
    } 
} 

class ProductInfoPanel extends React.Component { 
    render() { 
    // Info panel displays more information about a product. 
    return (
     <ul> 
     <li>{this.props.product.name}</li> 
     <li>{this.props.product.price}</li> 
     <li>{this.props.product.description}</li> 
     <li>{this.props.product.rating}</li> 
     <li>{this.props.product.review}</li> 
     </ul> 
    ); 
    } 
} 

這是我能想到的最好的,但使用狀態來跟蹤點擊的產品仍然聽起來對我來說是錯誤的。我的意思是,這不是一個組件的狀態,是嗎?

如果我能更新的引用props陣營組件從render方法之外,那麼我會盡量傳遞給ProductInfoPanel每個Product的引用,所以他們可以做他們的單擊處理程序更新。

有沒有辦法實現我想要的,並避免使用狀態來跟蹤點擊的內容?

回答

3

您可以使用類似flux的庫,例如reduxmobx等替代方案來從您的組件中刪除狀態管理,但我個人的感覺是保持儘可能簡單,直到您真的覺得會有顯着的好處在您的項目中添加另一個抽象層。

我以前默認使用redux來啓動項目,但後來有一次我踢了自己,結果發現增加一個引入redux實現的複雜性實際上是一個相當小而簡單的項目。我不知道是否需要知道什麼時候應該避免使用標準狀態並引入另一個庫來爲您管理它,但我已經瞭解到最簡單最簡單的方法可能是最安全的,你真的覺得在引入另一個依賴方面有實際的好處。


您當前密碼的建議的幾位......

你像這樣結合的功能屬性:

<Product product={product} clickHandler={this.onProductClicked.bind(this)}/> 

當你調用函數bind它實際上返回新的函數實例,因此React的協調器會將其視爲進入組件的新的道具,因此將始終重新呈現子組件樹。有些事情要注意。作爲一種替代方法,你可以在你的構造做早期綁定像這樣:

class ProductList extends React.Component { 
    constructor(props) { 
    super(props); 
    this.onProductClicked = this.onProductClicked.bind(this); 
    } 
    render() { 
    ... 
     <li key={index}> 
      <Product product={product} 
      clickHandler={this.onProductClicked}/> 
     </li> 
    ... 
    } 
} 

此外,你在哪裏提供index因爲他們獨特的key道具上面 - 你應該考慮使用從product模型的唯一標識符(如果它是可用)。這樣,如果您添加或刪除列表中的項目,React將獲得更多信息,以瞭解是否應該重新呈現所有Product組件實例。

例如:

render() { 
    ... 
    { 
     this.props.products.map((product) => 
     <li key={product.id}> 
      <Product product={product} 
      clickHandler={this.onProductClicked}/> 
     </li> 
    ) 
    } 

    ... 
} 

此處詳細瞭解這些概念: https://facebook.github.io/react/docs/advanced-performance.html

1

我覺得這很好。如果有更多的組件對SelectedProduct中的更改做出響應,那麼使父組件控制狀態的值將更加明顯。在你的情況下,它可能不是必要的,因爲只有一個組件改變。

但是,如果你Product也凸顯SelectedProduct迴應,和RecentlyViewedProducts列表以某種方式迴應了SelectedProduct,那就該SelectedProduct不是ProductInfoPanel的狀態,但較高的狀態變得明顯它是一個觀察者的應用程序的高級部分。