2015-08-27 37 views
0

我遇到問題更新React中的值。我也會在序言中說我是一個反應的小白,並且仍然試圖理解一些概念。反應如何更新道具項目點擊,而不是所有項目

我有一個組件,單擊時增加和減少一個值。問題是它會更新所有項目的所有道具,而不是點擊一個道具。

例如我有一個項目列表,我點擊1個項目來更新quantity它做的,但也更新其他項目的數量。所有這些項目都是相似的。還需要做的是它應該計算所有項目中的所有數量,並輸出一個不起作用的總數。

這與註解什麼,我試圖完成的圖像:

http://i.imgur.com/HlhPcym.png

任何幫助將不勝感激。

數量組件:

import React from 'react'; 
import If from '../utils/helpers'; 


var QuantityInput = React.createClass({ 
    getInitialState: function(props) { 
    return { 
     quantity: this.props.quantity 
    }; 
    }, 

    handleIncrement: function(e) { 
    this.props.handleIncrement(this.props.quantity + 1); 
    }, 

    handleDecrement: function(e) { 
    if (this.props.quantity > 1) { 
     this.props.handleDecrement(this.props.quantity - 1); 
    } 
    }, 

    handleChange: function(e) { 
    this.setState({ 
     quantity: this.props.quantity 
    }); 
    }, 

    render: function() { 
    return (
     <div className="quantity-input"> 
     <span className="button button--gray controls__quantity" onClick={this.handleDecrement}>-</span> 
     <div className="quantity" onChange={this.handleChange}>{this.props.quantity}</div> 
     <span className="button button--gray controls__quantity" onClick={this.handleIncrement}>+</span> 
     </div> 
    ); 
    } 
}); 

module.exports = QuantityInput; 

產品:

import React from 'react'; 
import If from '../utils/helpers'; 
import QuantityInput from '../components/quantity.js' 


var Product = React.createClass({ 
    getInitialState: function() { 
    return { 
     quantity: 0 
    } 
    }, 

    handleIncrement: function(e) { 
    this.setState({ 
     quantity: this.state.quantity + 1 
    }); 
    }, 

    handleDecrement: function(e) { 
    if (this.state.quantity > 1) { 
     this.setState({ 
     quantity: this.state.quantity - 1 
     }); 
    } 
    }, 

    handleChange: function(e) { 
    var value = e.target.value.replace(/[^0-9]/, ''); 

    value = (value == '' ? 1 : value); 
    value = parseInt(value); 

    this.setState({ 
     quantity: value 
    }); 
    }, 

    render: function() { 
    var content; 
    var self = this; 
    if (this.props.items.length > 0) { 
     this.props.items.map(function(product) { 
     var items = product.priceCode.map(function(priceCode) { 
      return (
      <div className="list-item" key={priceCode.priceCode_id}> 
       <div className="list-info list-info--cart"> 
       <div className="list-info__venue"> 
        <h3 className="event-title">{priceCode.priceCode_title}</h3> 
        <If condition={priceCode.priceCode_passcode}> 
        <input type="text" placeholder="Passcode" /> 
        </If> 
        <span className="event-details">{priceCode.priceCode_info}</span> 
       </div> 
       </div> 
       <div className="controls"> 
       <div className="list-info__price">${priceCode.priceCode_price}</div> 
       <QuantityInput quantity={self.state.quantity} handleChange={self.handleChange} handleIncrement={self.handleIncrement} handleDecrement={self.handleDecrement} /> 
       </div> 
      </div> 
     ) 
     }); 

     content = {items} 
     }); 
    } 

    return (
     <div> 
     {content} 
     </div> 
    ); 
    } 
}); 

var ProductContainer = React.createClass({ 
    getInitialState: function() { 
    return { 
     data: [], 
     quantity: 0 
    } 
    }, 

    componentWillMount: function() { 
    this.loadProducts(this.props.url); 
    }, 

    loadProducts: function(url) { 
    $.ajax({ 
     url: url, 
     dataType: 'json', 
     success: function(data) { 
     this.setState({ 
      data: data 
     }); 
     }.bind(this), 
     error: function(xhr, status, err, data) { 
     console.error(this.props.url, status, err.toString()); 
     }.bind(this) 
    }); 
    }, 

    _hasData: function() { 
    var displayedItems = this.state.data.filter(function(product) { 
     var match = product.priceCode.filter(function(priceCode) { 
     return priceCode.priceCode_title.toLowerCase(); 
     }); 

     return (match !== -1); 
    }.bind(this)); 

    return (
     <div> 
     <Product items={displayedItems} /> 
     </div> 
    ); 
    }, 

    render: function() { 
    if (this.state.data) { 
     return (
     <div className="price-code"> 
      {this._hasData()} 
      <div className="subtotal-wrapper"> 
      <a href="#" className="button button--gray">Clear Selections</a> 
      <div className="subtotal"> 
       Subtotal ({this.state.quantity}): 
      </div> 
      <a href="#" className="button">Find Tickets</a> 
      </div> 
     </div> 
    )   
    } else { 
     return <div>Loading...</div>; 
    } 

    return false 
    } 
}); 

module.exports = ProductContainer; 
+0

你可以發佈你想渲染的UI的例子嗎?截圖或其他東西? – Pcriulan

+0

當然,這是一些關於應該發生的註釋的圖像[http://i.imgur.com/HlhPcym.png](http://i.imgur.com/HlhPcym.png) –

+0

謝謝!現在更清晰了。你能用這張圖片更新你的問題嗎?由於我要根據我對這張圖片的回覆,對每個人都會更清楚:) – Pcriulan

回答

2

QuantityInput部件將分別獲得同樣的quantity,因爲你通過他們Product組件quantity狀態。

順便說一句,你沒有區分每個quantity,這是非常混亂。這是做這件事的一種方法:

我不會創建一個詳細的實施,但這裏是主要的點([...]表明你的代碼保持不變):

ProductContainer

var ProductContainer = React.createClass({ 
    getInitialState: function() { 
    return { 
     data: [], 
     subTotal: 0 
    } 
    }, 

    incrementSubTotal: function() { 
    this.setState({ 
     data: this.state.data, 
     subTotal: this.state.subTotal + 1 
    }); 
    }, 

    decrementSubTotal: function() { 
    this.setState({ 
     data: this.state.data, 
     subTotal: this.state.subTotal - 1 
    }); 
    }, 

    _hasData: function() { 
    [...] 

    return (
     <div> 
     <Product 
      items={displayedItems} 
      incrementSubTotal={this.incrementSubTotal} 
      decrementSubTotal={this.decrementSubTotal}/> 
     </div> 
    ); 
    }, 

    render: function() { 
    [...] 
     Subtotal ({this.state.subTotal}): 
    [...] 
    } 
}); 

產品

var Product = React.createClass({ 
    //this component is now stateless 

    render: function() { 
    [...] 

    // the following extract items from within this.props and lets the 'incrementSubTotal' and 
    // 'decrementSubTotal' in '...callbacks'. See http://facebook.github.io/react/docs/transferring-props.html 
    // for details. 
    var {items, ...callbacks} = this.props; 
    [...] 
     <QuantityInput {...callbacks}/> 
    [...] 

    return (
     <div> 
     {content} 
     </div> 
    ); 
    } 
}); 

QuantityInput

var QuantityInput = React.createClass({ 

    getInitialState: function() { 
    return { 
     quantity: 0 
    } 
    }, 

    handleIncrement: function(e) { 
    [...] 
    this.props.incrementSubTotal(); 
    }, 

    handleDecrement: function(e) { 
    [...] 
    this.props.decrementSubTotal(); 
    }, 

    render: function() { 
    return (
     <div className="quantity-input"> 
     <span className="button button--gray controls__quantity" onClick={this.handleDecrement}>-</span> 
     <div className="quantity">{this.state.quantity}</div> 
     <span className="button button--gray controls__quantity" onClick={this.handleIncrement}>+</span> 
     </div> 
    ); 
    } 
}); 

正如你可以看到我傳遞的回調,從子組件中更新父組件的狀態。 這裏不是一個很好的練習。如果您對MVC模型有所瞭解,更好的方法是將所有輸入的狀態保持在頂層組件上,充當「控制器視圖」組件。 單擊「+」或「 - 」按鈕時,應用程序應該觸發一個事件,以使ProductContainer知道某件事發生了變化,並且必須更新它的狀態。這正是(Flux)架構的作用,你應該明確地看看它:)

+0

謝謝你的詳細足夠的例子!也感謝您提出更好的方法來做事情的建議! –

+0

不客氣:)如果你決定嘗試Flux,也許這個另一個答案可以幫助你:http://stackoverflow.com/questions/28060493/react-flux-and-xhr-routing-caching/32224104#32224104 – Pcriulan

+0

謝謝,我會檢查出來!我確實有一個問題,我讀了你引用的帖子,但我想確保我理解它。在我嘗試訪問正確的所有方法(比如'handleIncrement'等等,並將這些保存在實際的''或我只是在'var'定義中傳遞那些元素,並且只用'{... callbacks}'離開組件調用?我已經嘗試了兩種方法,但不斷地獲取'this.props ...'不是函數 –

相關問題