在setState

时间:2018-06-08 15:43:22

标签: javascript reactjs

我有一个存储状态的主要组件,并有一个名为handleBtnClick的函数来操作状态值。

我有另一个组件在按下按钮时调用函数handleBtnClick。我有一个displayComponent,我传递状态值以显示在窗体中。

我知道setState是异步的,所以displayComponent值总是落后一步。如何使用setState中的回调来解决这个问题,还是有另一种方法?

MainComponent

class SomeComponent extends React.Component {
  constructor (props) {
    super (props)
    this.state = {value: 1}
  }

  handleBtnClick = (values) => {      
    const newValue = this.state.value * values;
    this.setState({value: newValue});
  }

  render() {
    return (
      <div>
        <ButtonComponent onClick={this.handleBtnClick} />              
        <DisplayComponent displayValue={this.state.value}/>
      </div>
    );
  }
}

ButtonComponent

class ButtonComponent extends React.Component {
  render() {
    return (
      <div>
        <button onClick={() => this.props.onClick(123)}> // pretent this value always changes
                    Button
        </button>
      </div>
    );
  }
}

DisplayComponent

class DisplayComponent extends React.Component {
  render() {
    return (
      <div>
        {this.probs.displayValue}
      </div>
    );
  }
}

修改

沙盒示例(感谢Shubham):https://codesandbox.io/s/5kx9yk7934

在第一个按钮上单击标签中显示的值为0,即使它应该是4.在第二次单击时它会更新为4.

如何在第一次点击时确保该值始终正确(即4)使用状态值进行计算。

2 个答案:

答案 0 :(得分:0)

setState将更新您的状态,并且在状态更改时,您的主要组件将以新状态重新渲染,因此您的isDisplayComponent将重新渲染。

你的DislayComponent有一个拼写错误:this.probs

您的按钮和显示都可以是无状态组件:

const DisplayComponent = ({displayValue}) => <div>{displayValue}</div>

由于onClick被反应用作点击监听器,因此更喜欢传递handleClick道具而不是onClick。

const ButtonComponent = ({handleClick}) => <div><button onClick={() => handleClick(123)}> </button></div>

答案 1 :(得分:0)

在您的沙箱中,SomeComponent组件未正确处理状态:有多个setState调用,这是异步的,并且还存储了三个值(value1,value2,total),当它只需要一个(要添加一堆操作数)时,你可以从每个渲染中派生总计:

import React from "react";
import { render } from "react-dom";
class ButtonComponent extends React.Component {
  render() {
    return (
      <div>
        <button onClick={() => this.props.onClick(2)}>
          {" "}
          // pretent this value always changes Button
        </button>
      </div>
    );
  }
}
class DisplayComponent extends React.Component {
  render() {
    return <div>{this.props.displayValue}</div>;
  }
}

class SomeComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { stack: [] };
    this.get_total = this.get_total.bind(this);
  }

  handleBtnClick = value => {
    this.setState({ stack: this.state.stack.concat(value) });
  };

  get_total() {
    return this.state.stack.reduce((result, value) => {
      return result + value;
    }, 0);
  }

  render() {
    return (
      <div>
        <ButtonComponent onClick={this.handleBtnClick} />
        <DisplayComponent displayValue={this.get_total()} />
      </div>
    );
  }
}

render(<SomeComponent />, document.getElementById("root"));