setState函数未定义

时间:2018-12-17 20:22:22

标签: javascript reactjs jsx

我是ReactJS的新手,正在尝试修改由API调用的响应填充的表单的值。我希望能够修改每一行中收到的主体并在另一个字段中获取它们的总和。 onChange处理函数是:

handleAmortScheduleChange(field , key ,e  ){
            const value = e.target.value;

            this.setState({
            [get_schedule[key][field]] : value,
            [get_emi_amount]:get_schedule[key]["principal"] + get_schedule[key]["interest"],
            [get_schedule[key]["closing_balance"]] : get_schedule[key]["starting_balance"] - get_emi_amount

           });                         
            var arr = document.getElementsByName('get_schedule_principal_here');
            var tot=0;
            for(var i=0;i<arr.length;i++){

                if(parseInt(arr[i].value))
                    tot += parseInt(arr[i].value);
            }
            document.getElementById('get_total_principal').value = tot;

        }

JSX代码为:

{this.state.get_schedule.map((row,key) =>

<div key={key} className="row aaaa">

    <div className="getAmort-form-group col-xs-12 col-sm-12 col-md-2 col-lg-2">
        <input ref = "get_schedule_emi_date" type="date" required="required" id="get_schedule_emi_date"  value={row.date} />
        <label for="input" className="getAmort-control-label">EMI Date</label><i className="getAmort-bar"></i>
    </div>
    <div className="getAmort-form-group col-xs-12 col-sm-12 col-md-2 col-lg-2">
        <input ref = "get_schedule_emi_amount" type="number" required="required" id="get_schedule_emi_amount"  value={row.amount}/>
        <label for="input" className="getAmort-control-label">EMI Amount</label><i className="getAmort-bar"></i>
    </div>
    <div className="getAmort-form-group col-xs-12 col-sm-12 col-md-2 col-lg-2">
        <input ref = "get_schedule_principal" type="number" required="required" id="get_schedule_principal" name="get_schedule_principal_here" value={row.principal} onChange={this.handleAmortScheduleChange.bind(this, "principal",key)}/>
        <label for="input" className="getAmort-control-label">Principal</label><i className="getAmort-bar"></i>
    </div>
    <div className="getAmort-form-group col-xs-12 col-sm-12 col-md-2 col-lg-2">
        <input ref = "get_schedule_interest" type="number" required="required" id="get_schedule_interest"   value={row.interest} onChange={this.handleAmortScheduleChange.bind(this, "principal",key)} />
        <label for="input" className="getAmort-control-label">Interest</label><i className="getAmort-bar"></i>
    </div>
    <div className="getAmort-form-group col-xs-12 col-sm-12 col-md-2 col-lg-2">
        <input ref = "get_schedule_starting_balance" type="number" required="required" id="get_schedule_starting_balance"  value={row.starting_balance }/>
        <label for="input" className="getAmort-control-label">Starting Balance</label><i className="getAmort-bar"></i>
    </div>
    <div className="getAmort-form-group col-xs-12 col-sm-12 col-md-2 col-lg-2">
        <input ref = "get_schedule_closing_balance" type="number" required="required" id="get_schedule_closing_balance"  value={row.closing_balance}/>
        <label for="input" className="getAmort-control-label">Closing Balance</label><i className="getAmort-bar"></i>
    </div>

</div>)}
<div className="row">
    <div className="getAmort-form-group col-xs-12 col-sm-12 col-md-2 col-lg-2">
        <input  type="number" required="required" id="get_total_principal" />
        <label for="input" className="getAmort-control-label">Total Principal</label><i className="getAmort-bar"></i>
    </div>

    <div className="getAmort-form-group col-xs-12 col-sm-12 col-md-2 col-lg-2">
        <input  type="number" required="required" id="get_total_interest" />
        <label for="input" className="getAmort-control-label">Total Interest</label><i className="getAmort-bar"></i>
    </div>
</div>

get_schedule是API响应中的一个数组数组,其中包含表单中所有字段的值。我实质上是在尝试更改用户输入的本金和利息的值,并在get_schedule数组中设置它们各自的值。

我在handleAmortScheduleChange函数中遇到的错误是 Uncaught ReferenceError: get_schedule is not defined。我也无法为利息或本金设置状态。我要去哪里错了,这有什么解决方案?

编辑1:根据要求,定义组件类中的get_schedule和其他一些参数。

class LoanDetails extends Component {

    constructor(props) {
        this.state={
            get_schedule            : [],
            get_interest            : 0,
            get_principal           : 0,
            get_starting_balance    : 0,
            get_closing_balance     : 0,
            get_emi_date            : 0,
            get_emi_amount          : 0,
     }
}

从API响应中设置为get_schedule的值为:

get_schedule: [{discount: 0, amount: 501, starting_balance: 1000, interest: 1, date: "2019-01-06",…},…]
0: {discount: 0, amount: 501, starting_balance: 1000, interest: 1, date: "2019-01-06",…}
amount: 501
closing_balance: 500
date: "2019-01-06"
discount: 0
interest: 1
principal: 500
starting_balance: 1000
1: {discount: 0, amount: 501, starting_balance: 500, interest: 1, date: "2019-02-06", closing_balance: 0,…}
amount: 501
closing_balance: 0
date: "2019-02-06"
discount: 0
interest: 1
principal: 500
starting_balance: 500

4 个答案:

答案 0 :(得分:2)

如果未定义错误setState,则会丢失此上下文。您能否为handleAmortScheduleChange函数尝试箭头功能?

    handleAmortScheduleChange = (field , key ,e  ) => {
        const value = e.target.value;

        this.setState({
        [get_schedule[key][field]] : value,
        [get_emi_amount]:get_schedule[key]["principal"] + get_schedule[key]["interest"],
        [get_schedule[key]["closing_balance"]] : get_schedule[key]["starting_balance"] - get_emi_amount

       });                         
        var arr = document.getElementsByName('get_schedule_principal_here');
        console.log(arr.length);
        console.log(arr);
        var tot=0;
        for(var i=0;i<arr.length;i++){

            if(parseInt(arr[i].value))
                tot += parseInt(arr[i].value);
                console.log(tot);
        }
        document.getElementById('get_total_principal').value = tot;

    }

如果错误未定义为get_schedule,则可能是因为您执行了异步操作,并且在呈现功能时还没有定义,我强烈建议您检查代码流。如果您添加更多代码,我可以为您提供更多线索,但同时尝试使用以下语法。

// double check if get_schedule is ready to use
{this.state.get_schedule && this.state.get_schedule.map((row,key) =>

    {
       /*  now map the row and key to inputs */
    }

}

要解决get_schedule中的get_schedule错误,您可以将函数更改为箭头函数并使用this.get_schedule

handleAmortScheduleChange = (field , key ,e  ) => {
    const value = e.target.value;

    this.setState({
    [this.get_schedule[key][field]] : value,
    [get_emi_amount]:this.get_schedule[key]["principal"] + this.get_schedule[key]["interest"],
    [this.get_schedule[key]["closing_balance"]] : this.get_schedule[key]["starting_balance"] - get_emi_amount

   });                         
    var arr = document.getElementsByName('get_schedule_principal_here');
    console.log(arr.length);
    console.log(arr);
    var tot=0;
    for(var i=0;i<arr.length;i++){

        if(parseInt(arr[i].value))
            tot += parseInt(arr[i].value);
            console.log(tot);
    }
    document.getElementById('get_total_principal').value = tot;

}

我修复了您的代码的沙盒版本,您可以在这里找到它。

我修复的是这些东西:

  1. 对于标签中的标签,请使用htmlFor而不是普通的for
  2. 您的某些输入没有onChangeHandler,我只是留下了一些onchange处理程序来解决该错误,但请确保以您喜欢的方式填充以下输入的处理程序。 (输入的EMI_Date,EMI_Amount,CLOSING和START Balance发生变化)...
  3. 主要错误我使用了不同的状态设置方法。

通常,如果您要对状态进行的更新取决于当前状态,我们会使用以下语法,因为这样更安全:)

 this.setState(prevState => ({
      value: prevState.value + 1
    })); 

https://codesandbox.io/s/o4k6nmr4l5

让我知道您的想法吗?没有错误,但是我对这种形式的计算一无所知:)

答案 1 :(得分:1)

您必须将其绑定到构造函数中:

this.handleAmortScheduleChange = this.handleAmortScheduleChange.bind(this);

答案 2 :(得分:0)

假设您已经定义了get_schedule函数,我看到的问题是您没有使用单词this来调用它。

您应该做类似的事情

this.get_schedule

答案 3 :(得分:0)

我终于做了一些修改,使我的代码可以正常工作。

  class Loan extends Component {
  constructor(props) {
    super(props);
    this.state = {

      field: "",
      get_schedule: [
        {
          amount: 2000,
          principal: 0,
          discount: 0,
          date: "2019-01-06",
          interest: 0,
          starting_balance: 1000,
          closing_balance: 0
        },
        {
          amount: 3000,
          principal: 0,
          discount: 0,
          date: "2019-02-06",
          interest: 0,
          starting_balance: 1500,
          closing_balance: 0
        }
      ]
    };
  }
  handleAmortScheduleChange = (key, field) => e => {
    const value = e.target.value;
    const { get_schedule, get_emi_amount } = this.state;
    const old_schedule = get_schedule[key];
    const new_get_schedule = [...get_schedule];
    new_get_schedule[key] = {
      ...old_schedule,
      [field]: value,
      closing_balance: old_schedule.starting_balance - get_emi_amount
    };
    this.setState({
      get_schedule: new_get_schedule,
      get_emi_amount: old_schedule.principal + old_schedule.interest
      // [get_schedule[key][field]]: value,
      // [get_emi_amount]: get_schedule[key]["principal"] + get_schedule[key]["interest"],
      // [get_schedule[key]["closing_balance"]]: get_schedule[key]["starting_balance"] - get_emi_amount,
    });
    var arr = document.getElementsByName("get_schedule_principal_here");
    var tot = 0;
    for (var i = 0; i < arr.length; i++) {
      if (parseInt(arr[i].value)) tot += parseInt(arr[i].value);
    }
    document.getElementById("get_total_principal").value = tot;
  };

  render() {
    const { get_schedule, get_emi_amount } = this.state;
    return (
      <div className="App">
        {this.state.get_schedule.map((row, key) => (
          <div key={key} className="row aaaa">
            <div className="getAmort-form-group col-xs-12 col-sm-12 col-md-2 col-lg-2">
              <input
                ref="get_schedule_emi_date"
                type="date"
                required="required"
                id="get_schedule_emi_date"
                value={row.date}
              />
              <label for="input" className="getAmort-control-label">
                EMI Date
              </label>
              <i className="getAmort-bar" />
            </div>
            <div className="getAmort-form-group col-xs-12 col-sm-12 col-md-2 col-lg-2">
              <input
                ref="get_schedule_emi_amount"
                type="number"
                required="required"
                id="get_schedule_emi_amount"
                value={get_schedule[key].amount}
              />
              <label for="input" className="getAmort-control-label">
                EMI Amount
              </label>
              <i className="getAmort-bar" />
            </div>
            <div className="getAmort-form-group col-xs-12 col-sm-12 col-md-2 col-lg-2">
              <input
                ref="get_schedule_principal"
                type="number"
                required="required"
                id="get_schedule_principal"
                name="get_schedule_principal_here"
                value={get_schedule[key].principal}
                onChange={this.handleAmortScheduleChange(key, "principal")}
              />
              <label for="input" className="getAmort-control-label">
                Principal
              </label>
              <i className="getAmort-bar" />
            </div>
            <div className="getAmort-form-group col-xs-12 col-sm-12 col-md-2 col-lg-2">
              <input
                ref="get_schedule_interest"
                type="number"
                required="required"
                id="get_schedule_interest"
                value={get_schedule[key].interest}
                onChange={this.handleAmortScheduleChange(key, "interest")}
              />
              <label for="input" className="getAmort-control-label">
                Interest
              </label>
              <i className="getAmort-bar" />
            </div>
            <div className="getAmort-form-group col-xs-12 col-sm-12 col-md-2 col-lg-2">
              <input
                ref="get_schedule_starting_balance"
                type="number"
                required="required"
                id="get_schedule_starting_balance"
                value={row.starting_balance}
              />
              <label for="input" className="getAmort-control-label">
                Starting Balance
              </label>
              <i className="getAmort-bar" />
            </div>
            <div className="getAmort-form-group col-xs-12 col-sm-12 col-md-2 col-lg-2">
              <input
                ref="get_schedule_closing_balance"
                type="number"
                required="required"
                id="get_schedule_closing_balance"
                value={get_schedule[key].closing_balance}
              />
              <label for="input" className="getAmort-control-label">
                Closing Balance
              </label>
              <i className="getAmort-bar" />
            </div>
          </div>
        ))}
        <div className="row">
          <div className="getAmort-form-group col-xs-12 col-sm-12 col-md-2 col-lg-2">
            <input type="number" required="required" id="get_total_principal" />
            <label for="input" className="getAmort-control-label">
              Total Principal
            </label>
            <i className="getAmort-bar" />
          </div>

          <div className="getAmort-form-group col-xs-12 col-sm-12 col-md-2 col-lg-2">
            <input type="number" required="required" id="get_total_interest" />
            <label for="input" className="getAmort-control-label">
              Total Interest
            </label>
            <i className="getAmort-bar" />
          </div>
        </div>
      </div>
    );
  }
}