2016-07-10 3 views
1

Вот чего я пытаюсь достичь. У меня есть два компонента React Product и ProductInfoPanel, показанный внутри компонента ProductList. Product отображает выбранную информацию о продукте, такую ​​как название продукта и цена. При щелчке по продукту в окне ProductInfoPanel будет показано больше деталей. Поэтому мне нужно пройти вау дважды, нажав на 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

Вы можете использовать флюсоподобную библиотеку, такую ​​как redux, или альтернативу, например mobx, чтобы удалить управление состоянием из вашего компонента, но мое личное чувство заключается в том, чтобы держать его как можно более простым, пока вы действительно не почувствуете, что будет значительная выгода добавив еще один слой абстракции в ваш проект.

Раньше я начинал проекты с использованием редуксов по умолчанию, но однажды я ударил себя, поскольку оказалось, что добавленная сложность внедрения реализации 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, но состояние высшего которая является наблюдателем.

Смежные вопросы