this.state的奇怪行为

时间:2017-09-14 07:33:45

标签: reactjs ecmascript-6

这是this问题的后续问题。我试图log两个复选框的值,无论是真还是假    我在checkbox中有两个<form><form>分配了onChange={this.checkBoxOnChange},它会在表单中的每次更改时触发checkBoxOnChange(event){..}函数。我正在尝试map_(Log)_状态(即是否检查它们)。所以,我最初在false this.state()constructor()取值为 render() { return ( <div> <form onChange={this.checkBoxOnChange.bind(this)}> <input type="checkbox" name="invoicestatus" value="BILLDED" />BILLDED<br /> <input type="checkbox" name="invoicestatus" value="PENDING" />PENDING<br /> </form> <ListData data={this.state.data}/> </div> ); } }; ,因为它们未被检查(最初)然后在每个事件上我分别试图改变那个值< em>(即如果为假,则为真,反之亦然) 但是,当我试图记录他们的输出时,他们打印的顺序错误。选中复选框甚至会更改另一个复选框的值。

这是render方法内的复选框的代码:

checkBoxOnChange()

这是同一个类(Component)中的checkBoxOnChange(event){ console.log("BILLDED"+this.state.billed+"PENDING"+this.state.pending); (event.target.value=='BILLDED') && (this.setState({billed:(!this.state.billed)})); (event.target.value=='PENDING') ? (this.setState({pending:(!this.state.pending)})) : null; console.log("BILLED"+this.state.billed+" PENDING"+this.state.pending); } 函数:

constructor(props){
    super(props);
    this.state = {
      data:[],
      billed:false,
      pending:false
     }
  }

初始值设置为:

setState()
  • 为什么我的错误值?
  • 如何使其按正确顺序工作?

这个问题this的帖子有所不同基于以下理由发帖:   - 因为这个问题的解决方案都提到Uncontrolled Components vs Controlled Components   - 如果我(或其他人)遵循上述条件,那么我还有(&amp;会)不知道的反应{{1}}的特征{{1}}提到的帖子。

2 个答案:

答案 0 :(得分:3)

在我看来,你过于复杂化了 不使用uncontrolled组件,而是使用controlled组件 只需为每个复选框设置一个处理程序:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      pending: false,
      billed: false
    };

    this.togglePending = this.togglePending.bind(this);
    this.toggleBilled = this.toggleBilled.bind(this);
  }

  togglePending() {
    this.setState({
      pending: !this.state.pending
    });
  }

  toggleBilled() {
    this.setState({
      billed: !this.state.billed
    });
  }

  render() {
    const { pending, billed } = this.state;
    return (
      <div>
        <input
          type="checkbox"
          name="invoicestatus"
          checked={billed}
          onChange={this.toggleBilled}
          value="BILLDED"
        />BILLDED<br />
        <input
          type="checkbox"
          name="invoicestatus"
          checked={pending}
          onChange={this.togglePending}
          value="PENDING"
        />PENDING<br />
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

答案 1 :(得分:3)

您的方法存在一些问题。

  1. 您正在使用不受控制的输入元素,但仍在使用将其值存储到state。使用不受控制或不受控制的组件,而不是混合组件。更多信息herehere

  2. 使用取决于先前状态值的值更新状态时,不应使用函数更新程序表单而不是对象表单。更多信息,here

      

    如果需要根据以前的状态设置状态,请阅读updater参数。

  3. 您应该知道setState()是异步的,因此在更新状态后立即登录控制台很可能会给您以前的状态。更多信息here

      

    setState()并不总是立即更新组件。它可以批量推迟更新或推迟更新。这会在调用this.state潜在陷阱后立即阅读setState()

  4. 我将如何做到这一点:

    class MyApp extends React.Component {
      constructor() {
        super();
        this.state = {
          pending: false,
          billed: false
        };
      }
    
      togglePending = () => {
        this.setState((prevState) => ({pending: !prevState.pending}));
      }
    
      toggleBilled = () => {
        this.setState((prevState) => ({billed: !prevState.billed}));
      }
    
      render() {
        let {pending, billed} = this.state;
        return (
          <div>
            <input type="checkbox" name="invoicestatus" checked={billed} onChange={this.toggleBilled} value="BILLDED" />BILLDED<br />
            <input type="checkbox" name="invoicestatus" checked={pending} onChange={this.togglePending} value="PENDING" />PENDING<br />
          </div>
        );
      }
    }
    
    ReactDOM.render(<MyApp />, document.getElementById("app"));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react-dom.js"></script>
    <div id="app"></div>

    如果你坚持使用你的方法,这里是如何解决它:

    class MyApp extends React.Component {
      constructor() {
        super();
        this.state = {
          pending: false,
          billed: false
        };
      }
    
      checkBoxOnChange(event){
        console.log("BILLDED"+this.state.billed+"PENDING"+this.state.pending);
        let obj = {};
        if (event.target.value == 'BILLDED') {
          this.setState({billed: !this.state.billed}, () => {
            console.log("BILLED"+this.state.billed+" PENDING"+this.state.pending);
          });
        } else if(event.target.value=='PENDING') {
          this.setState({pending: !this.state.pending}, () => {
            console.log("BILLED"+this.state.billed+" PENDING"+this.state.pending);
          });
        }
      }
    
      render() {
        return (
          <div>
          <form onChange={this.checkBoxOnChange.bind(this)}>
            <input type="checkbox" name="invoicestatus" value="BILLDED" />BILLDED<br />
            <input type="checkbox" name="invoicestatus" value="PENDING" />PENDING<br />
          </form>
        </div>
        );
      }
    }
    
    ReactDOM.render(<MyApp />, document.getElementById("app"));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react-dom.js"></script>
    <div id="app"></div>