React JS - Child 和 Parent 之间的通信和双重事件
React JS - Communication between Child and Parent and double events
我在制作一个小应用程序时遇到了问题
用于 React 中某些产品的价格计算。这是我的应用程序的样子:
我现在需要的是一个全局总数(ListItem 组件的部分总数的总和),但我不知道如何使用 React 来做到这一点。我尝试使用最小组件 (ListItem) 的相同 "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
});
},
但是这样只触发了这个事件,并没有更新状态。
可能我错过了什么。
Recapping 我需要的是将在 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
);
我认为 Redux 适合你。
它可以帮助您在不一定具有 child/parent 关系的组件之间传递属性。基本上,它创建了一个您可以从任何地方访问的全局状态。
关于 redux 有很多话要说(我们不会无缘无故地称它为 react/redux),如果你想用 React 做一些强大的事情,这是必备的。
您可以在 Redux 文档中找到更多信息!
您可以在父组件中添加一个函数来更改该组件的状态,然后将该函数作为 prop 发送给子组件。
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>
)
}
});
您可能想查看 Ksyqo 提到的 Redux。但是,对于此类需求,它可能并不完全是您所需要的,因为在您已经编写了现有应用程序代码的情况下,它会要求您在这个特定时刻应用各种样板和认知开销。
对于较小的项目,人们可能会发现您可以使用 MobX 替代方案,因为它更容易实现,尤其是在现有应用程序中。这也更容易推理。它几乎可以开箱即用,还需要一点魔法。
无论决定是什么,该图都适用于 Redux 和 MobX,并说明了 全局状态 与 父子链状态(前者显然更干净):
我在制作一个小应用程序时遇到了问题 用于 React 中某些产品的价格计算。这是我的应用程序的样子:
我现在需要的是一个全局总数(ListItem 组件的部分总数的总和),但我不知道如何使用 React 来做到这一点。我尝试使用最小组件 (ListItem) 的相同 "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
});
},
但是这样只触发了这个事件,并没有更新状态。 可能我错过了什么。
Recapping 我需要的是将在 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
);
我认为 Redux 适合你。
它可以帮助您在不一定具有 child/parent 关系的组件之间传递属性。基本上,它创建了一个您可以从任何地方访问的全局状态。
关于 redux 有很多话要说(我们不会无缘无故地称它为 react/redux),如果你想用 React 做一些强大的事情,这是必备的。
您可以在 Redux 文档中找到更多信息!
您可以在父组件中添加一个函数来更改该组件的状态,然后将该函数作为 prop 发送给子组件。
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>
)
}
});
您可能想查看 Ksyqo 提到的 Redux。但是,对于此类需求,它可能并不完全是您所需要的,因为在您已经编写了现有应用程序代码的情况下,它会要求您在这个特定时刻应用各种样板和认知开销。
对于较小的项目,人们可能会发现您可以使用 MobX 替代方案,因为它更容易实现,尤其是在现有应用程序中。这也更容易推理。它几乎可以开箱即用,还需要一点魔法。
无论决定是什么,该图都适用于 Redux 和 MobX,并说明了 全局状态 与 父子链状态(前者显然更干净):