2017-06-05 7 views
0

this.stateに格納されている計算を実行中のMemberというコンポーネントを書き込んでいますが、onChangeハンドラの1つの状態undefinedですが、値を入力する必要があります。例えばMember状態値が「未定義」状態onChange

import React from "react"; 

import {calcSCR, difference, multiply} from "../../utils/Calculations"; 
import {SCR_COEFF} from "../../constants/calc"; 

class Member extends React.Component { 

    constructor(props){ 
     super(props); 

     this.state = { 
      id: "1", 
      full_name: 'Mocked member 1', 
      role: 'Developer', 
      salary: 1650, 
      hourly_cost: 19.6, // SCR = (gross * coeff)/100 
      project_data: { 
       project_id: '1', 
       hourly_rate: 40, 
       occupation: 50, 
       estimate_hours: 70, 
       revenue: 2800,// revenue = estimate_hours * hourly_rate 
       cost: 1372,// cost = estimate_hours * hourly_cost 
       profit: 1428// profit = revenue - cost 
      } 
     }; 

     this.onSalaryChange = this.onSalaryChange.bind(this); 
     this.onHourlyCostChange = this.onHourlyCostChange.bind(this); 
     this.onHourlyRateChange = this.onHourlyRateChange.bind(this); 
     this.onEstimateHoursChange = this.onEstimateHoursChange.bind(this); 
     this.onRevenueChange = this.onRevenueChange.bind(this); 
     this.onCostChange = this.onCostChange.bind(this); 
     this.onNameChange = this.onNameChange.bind(this); 
     this.onOccupationChange = this.onOccupationChange.bind(this); 

     this.save = this.save.bind(this); 

    } 

    save(){ 

    } 

    onNameChange(e){ 
     this.setState({ 
      full_name: e.target.value 
     }) 
    } 

    onSalaryChange(e){ 
     let salary = e.target.value; 

     this.setState({ 
      salary: salary, 
      hourly_cost: calcSCR(salary, SCR_COEFF) 
     }) 
    } 

    onHourlyRateChange(e){ 
     let hourly_rate = e.target.value; 
     let estimate_hours = this.state.project_data.estimate_hours; 

     this.setState({ 
      project_data: { 
       hourly_rate: hourly_rate, 
       revenue: multiply(estimate_hours, hourly_rate) 
      } 
     }) 

    } 

    onOccupationChange(e){ 
     this.setState({ 
      project_data: { 
       occupation: e.target.value 
      } 
     }) 
    } 

    onEstimateHoursChange(e){ 
     let estimate_hours = e.target.value; 

     this.setState({ 
      project_data: { 
       estimate_hours: estimate_hours, 
       revenue: multiply(estimate_hours, this.state.project_data.hourly_rate), 
       cost: multiply(estimate_hours,this.state.hourly_cost) 
      } 
     }) 

    } 

    onHourlyCostChange(e){ 
     let hourly_cost = e.target.value; 
     this.setState({ 
      hourly_cost: hourly_cost, 
      project_data: { 
       cost: multiply(this.state.project_data.estimate_hours, hourly_cost) 
      } 
     }) 
    } 

    onRevenueChange(e){ 

     let revenue = e.target.value; 

     this.setState({ 
      project_data: { 
       revenue: revenue, 
       profit: difference(revenue,this.state.project_data.cost) 
      } 
     }) 
    } 

    onCostChange(e){ 

     let cost = e.target.value; 

     this.setState({ 
      project_data: { 
       cost: cost, 
       profit: difference(this.state.project_data.revenue,cost) 
      } 
     }) 
    } 

    render(){ 

     let {projectName} = this.props; 
     let data = this.state; 

     return (
      <div className="member"> 
       <a className="member__short_info" role="button" data-toggle="collapse" href={`#${data.id}`} aria-expanded="false" aria-controls={data.id}> 
        {data.full_name} 
       </a> 

       <div className="collapse member__member_full_info" id={data.id}> 
        <div className="member__full_info__row"> 
         <div className="row"> 
          <div className="col-sm-12 col-md-12 com-lg-12 member__full_info__header"> 
           {projectName} 
          </div> 

          <div className="col-sm-12 col-md-12 col-lg-6 member__full_info__column"> 
           <label htmlFor="full_name" className="member__full_info__label">Member full name:</label> 
           <input id="full_name" type="text" name="full_name" value={data.full_name} onChange={this.onNameChange}/> 
          </div> 

          <div className="col-sm-12 col-md-12 col-lg-6 member__full_info__column"> 
           <label htmlFor="salary" className="member__full_info__label">Salary:</label> 
           <input id="salary" type="text" name="salary" value={data.salary} onChange={this.onSalaryChange}/> 
          </div> 

          <div className="col-sm-12 col-md-12 col-lg-6 member__full_info__column"> 
           <label className="member__full_info__label">Hourly cost: </label> 
           <input id="hourly_cost" type="text" name="hourly_cost" value={data.hourly_cost} onChange={this.onHourlyCostChange}/> 
          </div> 

          <div className="col-sm-12 col-md-12 col-lg-6 member__full_info__column"> 
           <label htmlFor="hourly_rate" className="member__full_info__label">Hourly rate</label> 
           <input id="hourly_rate" type="text" name="hourly_rate" value={data.project_data.hourly_rate} onChange={this.onHourlyRateChange}/> 
          </div> 

          <div className="col-sm-12 col-md-12 col-lg-6 member__full_info__column"> 
           <label htmlFor="occupation" className="member__full_info__label">Occupation in project (%): </label> 
           <input id="occupation" type="text" name="occupation" value={data.project_data.occupation} onChange={this.onOccupationChange}/> 
          </div> 

          <div className="col-sm-12 col-md-12 col-lg-6 member__full_info__column"> 
           <label htmlFor="estimate_hours" className="member__full_info__label">Estimate hours: </label> 
           <input id="estimate_hours" type="text" name="estimate_hours" value={data.project_data.estimate_hours} onChange={this.onEstimateHoursChange}/> 
          </div> 

          <div className="col-sm-12 col-md-12 col-lg-4 member__full_info__column"> 
           <label className="member__full_info__label">Revenue: {data.project_data.revenue}</label> 
           {/*<input id="revenue" type="number" name="revenue" value={data.project_data.revenue} onChange={this.onRevenueChange}/>*/} 
          </div> 

          <div className="col-sm-12 col-md-12 col-lg-4 member__full_info__column"> 
           <label className="member__full_info__label">Cost: {data.project_data.cost}</label> 
           {/*<input id="cost" type="number" name="cost" value={data.project_data.cost} onChange={this.onCostChange}/>*/} 
          </div> 

          <div className="col-sm-12 col-md-12 col-lg-4 member__full_info__column"> 
           <label className="member__full_info__label">Profit: {data.project_data.profit}</label> 
          </div> 

          <div className="col-sm-12 member__full_info__save"> 
           <button className="modal-component positive-btn no-margin" onClick={this.save}>Save</button> 

          </div> 

         </div> 
        </div> 
       </div> 
      </div> 


     ); 
    } 
} 

export default Member; 


コンポーネント:onHourlyRateChange関数内estimate_hoursが変更後undefinedなります。

内側onEstimateHoursChangethis.state.project_data.hourly_ratethis.state.project_data.hourly_costundefinedになります。なぜ私はアイデアを持っていません。多分あなたは私にいくつかの助言を与えることができますか?

+0

あなた 'setState'は以前の状態を読んで必要とし、あなたのコンポーネントが頻繁に更新され、'を使用することを推奨されている場合:updatereact-addons-updateの置き換え)は、ネストされたプロパティを更新するために使用することができ

immutability-helperさんsetState(updaterFunction) 'APIを使用して、常に最新の状態になるようにしてください。 https://facebook.github.io/react/docs/react-component.html#setstate –

+0

イベントパラメータを割り当てる前に、イベントパラメータが定義されていないことを確認してください(アプリの境界を超えていることを確認してください)。 – Storm

答えて

1

すべてのネストされた状態に問題があります。つまり、project_data内にネストされているようです。コンポーネントは子要素を1回だけ更新しています。つまり、最初のキーを押したときに、それ以降のすべてのキーを押すと何も更新されず、代わりに非常に奇妙な入れ子状態の項目の値が未定義になります。これを回避するには、すべてのネストされた状態アイテムを単一レベルの状態アイテムとして移動できるようにすることができます。 例:

this.state = {    
      project_data: { hourly_rate: 40 } 
    } 

代わりに、あなたは、部分的に状態オブジェクトのトップレベルのプロパティを更新することができますが、ネストされたアップデートは機能しません親

this.state = {    
      project_data_hourly_rate: 40 
    } 
+0

ありがとうございます、私はそれについて考えただけでなく、残念ながら、入れ子になった状態を更新する最も簡単な方法だと思った。だから私はあなたの変種を使って問題を解決します – vladja

1

に子アイテムを移動することができます。

import update from 'immutability-helper'; 

const newData = update(myData, { 
    x: {y: {z: {$set: 7}}}, 
    a: {b: {$push: [9]}} 
}); 
+0

お返事ありがとうございます、それは良いですが、私は答えとして別のものを選択すると思います。主な理由は、もう1つの依存関係を追加したくないからです。 – vladja

+0

あなたは大歓迎です。シンプルなフラットな構造では不十分なときに、あなたの状態がより複雑になったときに、このテクニックを使用してください。 – m1kael

関連する問題