2017-03-07 47 views
0

我正在面对一个问题,针对React中某些产品的价格计算制作了一个小应用程序 。这是我的应用程序看起来像:React JS - 儿童与父母以及双重事件之间的沟通

Image 1

我现在需要的是有一个全球总量(部分总的列表项组件的总和),但我不知道该怎么做,与反应。我试图用最小的组件(列表项)的相同“的onChange”事件父触发事件,如:

handleChange:function(event){ 

    this.props.onChange(event.target); 

    const target = event.target; 
    const name = target.name; 
    const value = target.value; 

    this.setState({ 
    [name]: value 
    }); 
}, 

,但以这种方式仅此事件已被触发,并没有更新的状态。 可能我错过了一些东西。

回收我需要的是通过ListItem中计算的部分总数,在父组件Table中,以便我可以计算全局总数。

function Header(){ 
 
    return (
 
    <h1>Calcolo costo prodotti</h1> 
 
) 
 
} 
 

 
var ListItem = React.createClass({ 
 
    getInitialState: function(){ 
 
     return {name: this.props.value.product.name, costo: this.props.value.product.costo, quantita: this.props.value.product.quantita, totale: 0} 
 
    }, 
 
    
 
    render: function(){ 
 
    return(
 
     <tr> 
 
     <td><input type="text" name="name" value={this.state.name} onChange={this.handleChange} placeholder="Nome..."/></td> 
 
     <td><input type="text" name="costo" value={this.state.costo} onChange={this.handleChange} placeholder="Costo unitario..."/></td> 
 
     <td><input type="text" name="quantita" value={this.state.quantita} onChange={this.handleChange} placeholder="Quantità..."/></td> 
 
     <td className="total">{this.calcoloTotale()}</td> 
 
     </tr> 
 
    ) 
 
    }, 
 
    
 
    handleChange:function(event){ 
 
    const target = event.target; 
 
    const name = target.name; 
 
    const value = target.value; 
 
    
 
    this.setState({ 
 
     [name]: value 
 
    }); 
 
    }, 
 
    
 
    calcoloTotale: function(){ 
 
    var Ltotale = this.state.costo * this.state.quantita; 
 
    this.setState({totale: Ltotale}); 
 
    return Ltotale; 
 
    } 
 
}); 
 
    
 
    
 
var Table = React.createClass({ 
 
    getInitialState: function(){ 
 
    return { totale: 0 } 
 
    }, 
 
    
 
    render: function(){ 
 
    return(
 
     <div> 
 
     <table> 
 
      <tr> 
 
      <th>Nome</th> 
 
      <th>Prezzo</th> 
 
      <th>Quantità</th> 
 
      <th>Totale</th> 
 
      </tr> 
 
      {this.props.items.map((prodotto) => 
 
      <ListItem key={prodotto.id} value={prodotto}/> 
 
     )} 
 
     </table> 
 
     </div> 
 
    ) 
 
    } 
 
}); 
 

 
var AddNewRow = React.createClass({ 
 
    render: function(){ 
 
    return(
 
     <div> 
 
     <button onClick={this.props.onClick}>+</button> 
 
     Aggiungi prodotto 
 
     </div> 
 
    ) 
 
    } 
 
}); 
 

 
var Calculator = React.createClass({ 
 
    getInitialState: function(){ 
 
    return { 
 
     counter: 2, lists: [{id: "0", product: {name: "Esempio 1",costo: "25",quantita: "3"}}, {id: "1", product: {name: "Esempio 2",costo: "32",quantita: "4"}}] 
 
    } 
 
    }, 
 
    
 
    render: function(){ 
 
    return (
 
     <div className="container"> 
 
     <Header /> 
 
     <Table items={this.state.lists} ids={this.counter}/> 
 
     <AddNewRow onClick={this.addRow}/> 
 
     </div> 
 
    ) 
 
    }, 
 
    
 
    addRow: function(){ 
 
    this.setState({counter: this.state.counter + 1}); 
 
    var listItem = {id: this.state.counter, product:{name:"", costo: "", quantita: ""}}; 
 
    var allItem = this.state.lists.concat([listItem]) 
 
    this.setState({lists: allItem}); 
 
    } 
 
}); 
 

 
ReactDOM.render(
 
    <Calculator />, 
 
    document.body 
 
);

编辑1:

var totalVec = new Array(); 
 

 
function Header(){ 
 
    return (
 
    <h1>Calcolo costo prodotti</h1> 
 
) 
 
} 
 

 
var ListItem = React.createClass({ 
 
    getInitialState: function(){ 
 
     return {name: this.props.value.product.name, costo: this.props.value.product.costo, quantita: this.props.value.product.quantita} 
 
    }, 
 
    
 
    render: function(){ 
 
    return(
 
     <tr> 
 
     <td><input type="text" name="name" value={this.state.name} onChange={this.handleChange} placeholder="Nome..."/></td> 
 
     <td><input type="text" name="costo" value={this.state.costo} onChange={this.handleChange} placeholder="Costo unitario..."/></td> 
 
     <td><input type="text" name="quantita" value={this.state.quantita} onChange={this.handleChange} placeholder="Quantità..."/></td> 
 
     <td className="total">{this.calcoloTotale()}</td> 
 
     </tr> 
 
    ) 
 
    }, 
 
    
 
    handleChange:function(event){ 
 
    const target = event.target; 
 
    const name = target.name; 
 
    const value = target.value; 
 
    
 
    this.setState({ 
 
     [name]: value 
 
    }); 
 
    
 
    this.props.updateGlobalTotal(); 
 
    }, 
 
    
 
    calcoloTotale: function(){ 
 
    var Ltotale = this.state.costo * this.state.quantita; 
 
    totalVec[this.props.value.id] = Ltotale; 
 
    return Ltotale; 
 
    } 
 
}); 
 
    
 
    
 
var Table = React.createClass({ 
 
    getInitialState: function(){ 
 
    return { totale: 0 } 
 
    }, 
 
    
 
    render: function(){ 
 
    return(
 
     <div> 
 
     <table> 
 
      <tr> 
 
      <th>Nome</th> 
 
      <th>Prezzo</th> 
 
      <th>Quantità</th> 
 
      <th>Totale</th> 
 
      </tr> 
 
      {this.props.items.map((prodotto) => 
 
      <ListItem key={prodotto.id} value={prodotto} updateGlobalTotal={this.updateGlobalTotal}/> 
 
     )} 
 
     </table> 
 
     <h1>{this.state.totale}</h1> 
 
     </div> 
 
    ) 
 
    }, 
 
    
 
    componentDidMount: function(){ 
 
    var total = 0; 
 
    for(var i = 0; i < this.props.ids; i++){ 
 
     total += totalVec[i]; 
 
    } 
 
    
 
    this.setState({totale: total}); 
 
    }, 
 
    
 
    updateGlobalTotal: function(){ 
 
    var total = 0; 
 
    for(var i = 0; i < this.props.ids; i++){ 
 
     total += totalVec[i]; 
 
    } 
 
    
 
    this.setState({totale: total}); 
 
    } 
 
    
 
}); 
 

 
var AddNewRow = React.createClass({ 
 
    render: function(){ 
 
    return(
 
     <div> 
 
     <button onClick={this.props.onClick}>+</button> 
 
     Aggiungi prodotto 
 
     </div> 
 
    ) 
 
    } 
 
}); 
 

 
var Calculator = React.createClass({ 
 
    getInitialState: function(){ 
 
    return { 
 
     counter: 2, lists: [{id: "0", product: {name: "Esempio 1",costo: "25",quantita: "3"}}, {id: "1", product: {name: "Esempio 2",costo: "32",quantita: "4"}}] 
 
    } 
 
    }, 
 
    
 
    render: function(){ 
 
    return (
 
     <div className="container"> 
 
     <Header /> 
 
     <Table items={this.state.lists} ids={this.state.counter}/> 
 
     <AddNewRow onClick={this.addRow}/> 
 
     </div> 
 
    ) 
 
    }, 
 
    
 
    addRow: function(){ 
 
    this.setState({counter: this.state.counter + 1}); 
 
    var listItem = {id: this.state.counter, product:{name:"", costo: "", quantita: ""}}; 
 
    var allItem = this.state.lists.concat([listItem]) 
 
    this.setState({lists: allItem}); 
 
    } 
 
}); 
 

 
ReactDOM.render(
 
    <Calculator />, 
 
    document.body 
 
);

回答

0

您可以在父项中添加一个更改该组件状态的函数,然后将该函数作为通道发送给子项。

var ListItem = React.createClass({ 
 
    getInitialState: function(){ 
 
     return {name: this.props.value.product.name, costo: this.props.value.product.costo, quantita: this.props.value.product.quantita, totale: 0} 
 
    }, 
 
    
 
    ... 
 
    
 
    calcoloTotale: function(){ 
 
    var Ltotale = this.state.costo * this.state.quantita; 
 
    this.props.updateGlobalTotal(Ltotale); 
 
    this.setState({totale: Ltotale}); 
 
    return Ltotale; 
 
    } 
 
}); 
 
    
 
    
 
var Table = React.createClass({ 
 
    getInitialState: function(){ 
 
    return { totale: 0 } 
 
    }, 
 
    updateGlobalTotal: function(value){ 
 
     this.setState({totale: this.state.totale + value}) 
 
    } 
 
    
 
    render: function(){ 
 
    return(
 
     <div> 
 
     <table> 
 
      <tr> 
 
      <th>Nome</th> 
 
      <th>Prezzo</th> 
 
      <th>Quantità</th> 
 
      <th>Totale</th> 
 
      </tr> 
 
      {this.props.items.map((prodotto) => 
 
      <ListItem key={prodotto.id} value={prodotto} updateGlobalTotal={this.updateGlobalTotal}/> 
 
     )} 
 
     </table> 
 
     </div> 
 
    ) 
 
    } 
 
});

+0

您的解决方案部分工作,我做了一些调整,但有性能问题。如果您可以退房,我会将新代码放在帖子上。谢谢 –

0

我觉得Redux是为你做的。

它可以帮助您传递不必具有子/父关系的组件之间的属性。基本上,它创建了一个可以从任何地方访问的全局状态。

关于redux还有很多话要说(我们不会把它称为react/redux),如果你想用React做一些强大的功能,这是必须要做的。

您可以在Redux文档中找到更多信息!

0

你可能想看看终极版为Ksyqo提及。然而,对于这样的需求,它可能并不完全是你所需要的,因为它需要你在这个特定的时刻应用各种各样的样板和认知开销,当你已经编写了现有的应用代码时。

对于较小的项目,可能会发现,您可以使用MobX替代方案,因为它更容易实现,尤其是在现有应用程序中实现。推理起来也很容易。它会开箱即用,并带有一点魔力。

无论决定是,此图适用于这两个终极版和MobX真实的,说明了全局状态问题VS 亲子链状态(前者显然是更清洁):

enter image description here

+0

MobX似乎是一个很好的方法来做到这一点。我已经尝试了@Joakim Tangnes解决方案,它工作但有性能问题,使输入类型真的很慢。 –