2017-03-07 11 views
0

私はちょっとしたアプリケーションを作る問題に直面しています。 いくつかの製品をReactで価格計算しています。この私のアプリケーションがどのように見えるかです:React JS - 子どもと親の間のコミュニケーションと二重イベント

Image 1

私が今必要なものは世界全体(のListItem要素の部分合計の合計)を持っていることですが、私はそれを行う方法がわかりません反応する。私のような親にイベントトリガーする最小の構成要素(の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 
    }); 
}, 

をしかし、この方法でのみ、このイベントがトリガされたと状態を更新しませんでした。 おそらく私は何かを逃しています。

私が必要とするのは、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 
 
);

EDIT 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があなたのために作られていると思います。

必ずしも子/親の関係がないコンポーネント間でプロパティを渡すのに役立ちます。基本的には、どこからでもアクセスできるグローバルな状態を作成します。

レフィックスについて何度も言いたいことはありませんが(React/reduxは何の理由もありません)、これはReactで強力なことをしたい場合には欠かせないものです。

詳細は、Reduxのドキュメントを参照してください。

0

あなたはKsyqoが述べたようにReduxのをチェックアウトすることができます。しかし、このようなニーズのためには、既存のアプリケーションコードがすでに書かれているときに、この特定の瞬間に多種多様な定型文や認知的なオーバーヘッドを適用する必要があるため、必要なものではないかもしれません。

小規模なプロジェクトでは、より良い結果を得るために、特に既存のアプリケーションで実装するのが少し容易なので、MobXを使用することができます。それはまた、推論するのがずっと簡単です。それは、魔法の少し関与すると、ほとんどの場合、ボックスの外で動作します。意思決定が何であれ

は、このグラフはReduxのとMobXの両方に当てはまる、と(前者はよりクリーン明らかである)親子の連鎖状態グローバル状態の問題を示しています

enter image description here

+0

MobXはこれを行う良い方法のようです。 @ Joakim Tangnesのソリューションを試してみましたが、うまくいきましたが、入力タイプを遅くするようなパフォーマンス上の問題があります。 –

関連する問題