for循环在React js中

时间:2019-06-22 19:59:03

标签: reactjs

我正在尝试更新此值,但是即使条件为真,只要我console.log总是0

import React, { Component } from "react";

interface orderInformation {
  customer: number;
  picklePrice: number;
  breadPrice: number;
}

interface ComponentState {
  customer: number;
  picklePrice: number;
  breadPrice: number;
  error: string;
  finalPickleCost: number;
  finalBreadCost: number;
  pickleCounter: number;
  breadCounter: number;
}

export default class pickleSandwich extends Component<
  orderInformation,
  ComponentState
> {
  constructor(props: orderInformation) {
    super(props);

    //initializing variables to undefined
    this.state = {
      customer: 0,
      picklePrice: 0,
      breadPrice: 0,
      finalBreadCost: 0,
      finalPickleCost: 0,
      pickleCounter: 0,
      breadCounter: 0,
      error: ""
    };
    this.handleChange = this.handleChange.bind(this);
  }

  //Get information for the user
  getInfo = orderInformation => {
    orderInformation.preventDefault();

    const { customer, picklePrice, breadPrice } = this.state;
    console.log("customer", customer);
    console.log("pickle", picklePrice);
    console.log("bread", breadPrice);
    if (customer > 0) {
      for (var i = 0; i < customer; i++) {
        if (i % 3 === 0) {
          this.setState({
            pickleCounter: this.state.pickleCounter + 2,
            breadCounter: this.state.breadCounter + 3
          });
        } else {
          this.setState({
            pickleCounter: this.state.pickleCounter + 1,
            breadCounter: this.state.breadCounter + 2
          });
        }
      }
    } else {
      this.setState({
        error: "Please enter amount of customer"
      });
    }
    console.log("pickle Counter", this.state.pickleCounter);
    console.log("breadCounter", this.state.breadCounter);
  };

  handleChange = e => {
    this.setState({ [e.target.name]: e.target.value } as any);
  };

  render() {
    // const { customer, finalPickleCost, finalBreadCost } = this.state;

    return (
      <form onSubmit={this.getInfo}>
        <p>Get the information of the order!</p>
        <input
          type="text"
          id="customer"
          value={this.state.customer}
          placeholder="Amount of Customers"
          name="customer"
          onChange={this.handleChange}
          required
        />
        <input
          type="text"
          id="picklePrice"
          placeholder="Price of Pickle"
          value={this.state.picklePrice}
          name="picklePrice"
          onChange={this.handleChange}
          required
        />

        <input
          type="text"
          id="breadBrice"
          placeholder="Price of Bread"
          value={this.state.breadPrice}
          name="breadPrice"
          onChange={this.handleChange}
          required
        />
        <button type="submit" onClick={this.getInfo}>
          Get Information{" "}
        </button>
      </form>
    );
  }
}

我希望它更新值,以便我可以计算最终成本。

4 个答案:

答案 0 :(得分:4)

反应的setState是异步的,这意味着到您到达console.log时,状态可能尚未更新。

有关此行为的更多信息,请参见thisthis,一般请参见setState

要避免此问题,可以使用setState的回调方法,该回调方法在执行状态更新后便会触发:

this.setState(prevState => ({
    pickleCounter: prevState.pickleCounter + 1,
    breadCounter: prevState.breadCounter + 2
}), () => {
    // once you're here the state updated successfully
});

答案 1 :(得分:0)

设置状态是一个异步函数,因此,如果在同一函数中调用新状态,则通常无法访问该新状态,除非您为setState函数使用回调:

this.setState({...content...}, callbackFunction)

编辑

使用Tobias最初提到的某项功能(如他所描述的那样无效)给了我一个主意。在这种情况下使用异步等待的一种方法是添加一个自定义函数,以使setState返回promise。

setStateAsync(state) {
    return new Promise((resolve) => {
      this.setState(state, resolve)
    });
}

您可以使用它使函数等待状态被设置。

setStateAsync(state) {
  return new Promise((resolve) => {
    this.setState(state, resolve)
  });
}

//Get information for the user
getInfo = async orderInformation => {
  orderInformation.preventDefault();

  const {
    customer,
    picklePrice,
    breadPrice
  } = this.state;
  console.log("customer", customer);
  console.log("pickle", picklePrice);
  console.log("bread", breadPrice);
  if (customer > 0) {
    for (var i = 0; i < customer; i++) {
      if (i % 3 === 0) {
        await this.setStateAsync({
          pickleCounter: this.state.pickleCounter + 2,
          breadCounter: this.state.breadCounter + 3
        });
      } else {
        await this.setStateAsync({
          pickleCounter: this.state.pickleCounter + 1,
          breadCounter: this.state.breadCounter + 2
        });
      }
    }


  } else {
    await this.setStateAsync({
      error: "Please enter amount of customer"
    });
  };
  console.log("pickle Counter", this.state.pickleCounter);
  console.log("breadCounter", this.state.breadCounter);
};

答案 2 :(得分:0)

反应setState()可能是异步的,这意味着更新一个值然后将其合并可能会给您旧数据,这样做是错误的

// wrong, anti-pattern
this.setState({
  pickleCounter: this.state.pickleCounter + 2,
  breadCounter: this.state.breadCounter + 3
});

更好的方法

  

setState(updater [,回调])

//  good
this.setState((prevState) => {
  return { 
    pickleCounter: prevState.pickleCounter + 2,
    breadCounter: prevState.breadCounter + 3
  }
});

工作示例

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js"></script>

<div id="root"></div>

<script type="text/babel">

class App extends React.Component {
  //initializing variables to undefined
  state = {
    customer: 0,
    picklePrice: 0,
    breadPrice: 0,
    finalBreadCost: 0,
    finalPickleCost: 0,
    pickleCounter: 0,
    breadCounter: 0,
    error: ""
  };

  handleChange = e => {
    this.setState({ [e.target.name]: e.target.value }
    );
  };

  //Get information for the user
    getInfo = async (orderInformation) => {
    orderInformation.preventDefault();

    const { customer, picklePrice, breadPrice } = this.state;
    console.log("customer", customer);
    console.log("pickle", picklePrice);
    console.log("bread", breadPrice);
    if (customer > 0) {
      for (var i = 0; i < customer; i++) {
        if (i % 3 === 0) {
          await this.setState((prevState) => {
            return {
              pickleCounter: prevState.pickleCounter + 2,
              breadCounter: prevState.breadCounter + 3
            }
          }, () => {
            console.log("pickle Counter", this.state.pickleCounter);
            console.log("breadCounter", this.state.breadCounter);
          });
        }
        else {
         await this.setState((prevState) => {
            return {
              pickleCounter: prevState.pickleCounter + 1,
              breadCounter: prevState.breadCounter + 2
            }
          }, () => {
            console.log("pickle Counter", this.state.pickleCounter);
            console.log("breadCounter", this.state.breadCounter);
          });
        }
      }


    } else {
      this.setState({
        error: "Please enter amount of customer"
      });
    };
  };
  
  render() {
    // const { customer, finalPickleCost, finalBreadCost } = this.state;

    return (
      <form onSubmit={this.getInfo}>
        <p>Get the information of the order!</p>
        <input
          type="text"
          id="customer"
          value={this.state.customer}
          placeholder="Amount of Customers"
          name="customer"
          onChange={this.handleChange}
          required
        />
        <input
          type="text"
          id="picklePrice"
          placeholder="Price of Pickle"
          value={this.state.picklePrice}
          name="picklePrice"
          onChange={this.handleChange}
          required
        />

        <input
          type="text"
          id="breadBrice"
          placeholder="Price of Bread"
          value={this.state.breadPrice}
          name="breadPrice"
          onChange={this.handleChange}
          required
        />
        <button type="submit" onClick={this.getInfo}>Get Information </button>

      </form>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
</script>

您可以将回调传递给setState,在setState完成设置状态后将调用该回调。

this.setState((prevState) => {
  pickleCounter: prevState.pickleCounter + 2,
  breadCounter: prevState.breadCounter + 3
}, () => {
  // code here
});

或使用异步/等待

await this.setState({...})

异步/等待示例

没有异步/等待,状态可能是异步的。

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js"></script>

<div id="root"></div>

<script type="text/babel">

class App extends React.Component {

  state = {
    name: 'React'
  };


  componentDidMount = () => {

    this.setState({
      name: 'Peter'
    });

    console.log('logs old value: ', this.state.name);
  }

  render() {
    return (
      <div>
        <p>{this.state.name}</p>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
</script>

使用异步/等待

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js"></script>

    <div id="root"></div>

    <script type="text/babel">

    class App extends React.Component {

      state = {
        name: 'React'
      };


      componentDidMount = async () => {

        await this.setState({
          name: 'Peter'
        });

        console.log('logs new value: ', this.state.name);
      }

      render() {
        return (
          <div>
            <p>{this.state.name}</p>
          </div>
        );
      }
    }

    ReactDOM.render(<App />, document.getElementById("root"));
    </script>

请参阅以下文档。

State Updates May Be Asynchronous

setState

答案 3 :(得分:0)

您可以更新这样的值

if(i%3 === 0)
{
  this.setState((prevState)=>{
    return {
      pickleCounter: prevState.pickleCounter + 2,
      breadCounter:  prevState.breadCounter + 3
    }

  });
}

这里,在this.setState()内,我们不仅提供了返回新状态的功能,而且还提供了返回旧状态的功能,而不仅仅是提供新状态。您可以为先前的状态选择任何变量名称,而不是prevState