Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript React.js理解setState_Javascript_Reactjs - Fatal编程技术网

Javascript React.js理解setState

Javascript React.js理解setState,javascript,reactjs,Javascript,Reactjs,我一直在尝试通过编写一个小型计算器应用程序来学习React.js。我认为事情进展得很顺利,直到我了解到setState是异步的,因此我的突变不会立即应用 因此,我的问题是,根据添加到输入中的值,保持运行总数的最佳方法是什么。以以下为例: var Calculator = React.createClass({ total : 0, getInitialState : function(){ return { value : '0' }; }, o

我一直在尝试通过编写一个小型计算器应用程序来学习React.js。我认为事情进展得很顺利,直到我了解到setState是异步的,因此我的突变不会立即应用

因此,我的问题是,根据添加到输入中的值,保持运行总数的最佳方法是什么。以以下为例:

var Calculator = React.createClass({
  total : 0,

  getInitialState : function(){
    return { 
      value : '0'
    };
  },

  onValueClicked : function (value) {
    var actual, total, current = this.state.value;

    if(value === '+') {
      actual = this.total = parseInt(this.total, 10) + parseInt(current, 10);
    } else {
      if(parseInt(current, 10) === 0) {
        actual = value;
      } else {
        actual = current.toString() + value;
      }
    }

    this.setState({ value : actual });
  },

  render : function () {
    return (
      <div className="calc-main">
        <CalcDisplay value={this.state.value} />
        <CalcButtonGroup range="0-10" onClick={this.onValueClicked} />
        <CalcOpButton type="+" onClick={this.onValueClicked} />
      </div>
    )
  }
});

var CalcDisplay = React.createClass({
  render : function () {
    return (
      <input type="text" name="display" value={this.props.value} />
    );
  }
});

var CalcButtonGroup = React.createClass({
  render : function () {
    var i, buttons = [], range = this.props.range.split('-');

    for(i = range[0]; i < range[1]; i++) {
      var handler = this.props.onClick.bind(null, i);

      buttons.push(<CalcNumberButton key={i} onClick={ handler } />);
    }

    return (
      <div className="calc-btn-group">{ buttons }</div>
    );
  }
});

var CalcNumberButton = React.createClass({
  render : function () {
    return (
      <button onClick={this.props.onClick}>{this.props.key}</button>
    );
  }
});

var CalcOpButton = React.createClass({
  render : function () {
    var handler, op = this.props.type;

    handler = this.props.onClick.bind(null, op);

    return (
      <button onClick={handler}>{op}</button>
    );
  }
});

React.renderComponent(<Calculator />, document.getElementById('container'));
var Calculator=React.createClass({
总数:0,
getInitialState:函数(){
返回{
值:“0”
};
},
onValueClicked:函数(值){
var实际值、总计值、当前值=this.state.value;
如果(值=='+'){
实际=this.total=parseInt(this.total,10)+parseInt(current,10);
}否则{
if(parseInt(当前,10)==0){
实际=价值;
}否则{
实际值=当前.toString()+值;
}
}
this.setState({value:actual});
},
渲染:函数(){
返回(
)
}
});
var CalcDisplay=React.createClass({
渲染:函数(){
返回(
);
}
});
var CalcButtonGroup=React.createClass({
渲染:函数(){
变量i,按钮=[],范围=this.props.range.split('-');
对于(i=范围[0];i<范围[1];i++){
var handler=this.props.onClick.bind(null,i);
按钮;
}
返回(
{按钮}
);
}
});
var CalcNumberButton=React.createClass({
渲染:函数(){
返回(
{this.props.key}
);
}
});
var CalcOpButton=React.createClass({
渲染:函数(){
变量处理程序,op=this.props.type;
handler=this.props.onClick.bind(null,op);
返回(
{op}
);
}
});
React.renderComponent(,document.getElementById('container');
在上面的例子中,我完全放弃了将总数存储在州内,而将其保存在州外。我已经读到,当setState完成时,您可以运行回调,但对于计算器,我需要它快速更新。如果每次按下按钮都没有更新状态,而我又很快按下了按钮,那么事情就会失去同步。是回拨我所错过的全部,还是我的想法完全错误


感谢您的帮助

它是异步的,但是比最快的人类点击要快得多


除此之外,您应该在componentDidMount中声明实例变量,例如

componentDidMount:function(){
这个总数=0;
}
。。。但在这种情况下,您可能希望将其存储在状态中


.split返回字符串数组,如果要使用数字:

range=this.props.range.split('-').map(数字)
或者使用以下其中一种方法完全避免使用字符串(首选):


您已经为业务逻辑状态定义了
total
变量。为什么不存储更多这样的信息呢

var Calculator = React.createClass({
  previous: 0, // <-- previous result
  current: 0, // <-- current display
  op: '', // <-- pending operator

  getInitialState : function(){
    return { 
      value : '0'
    };
  },

  onValueClicked : function (value) {
    var actual;

    if(value === '+') {
      this.previous = this.current;
      this.op = '+';
      actual = 0; // start a new number
    } else if (value === '=') {
      if (this.op === '+') {
        actual = this.previous + this.current;
      } else {
        actual = this.current; // no-op
      }
    } else {
      actual = current * 10 + value;
    }

    this.current = actual; // <-- business logic state update is synchronous
    this.setState({ value : String(actual) }); // <-- this.state is only for UI state, asynchronous just fine
  },

  render : function () {
    return (
      <div className="calc-main">
        <CalcDisplay value={this.state.value} />
        <CalcButtonGroup range="0-10" onClick={this.onValueClicked} />
        <CalcOpButton type="+" onClick={this.onValueClicked} />
        <CalcOpButton type="=" onClick={this.onValueClicked} />
      </div>
    )
  }
});
var Calculator=React.createClass({

previous:0,//老实说,如果您根本不需要在
render
函数中使用
this.total
,那么将其保持在状态之外是很好的。只有当对其进行任何更改时,才需要将其置于状态
始终
导致重新渲染。如果您在更改此.total时实际上不需要始终重新渲染,则您可以让事情保持原样。如果我没有弄错的话,在当前的实现中,如果您调用
setState
来响应一个事件,那么在调度任何进一步的事件之前,状态将得到解决。我想部分问题在于我是控制台。正在记录状态值。但是我发现,如果我尝试存储多个项目,我会n状态,并在一个位置和另一个位置更改一个字段-这两个值将不同步。即,如果我将操作数存储在状态中并在下一次交互中检查其存在性-它将不会总是被设置。我不同意,但在这种情况下,您可能希望将其存储在状态中。
状态
仅用于UI仅限tate,使用另一个(订阅)用于逻辑状态的变量。您需要将用于生成渲染输出的数据设置为状态+道具。这样您就可以存储总数或操作序列,或者以您希望的方式来表示它。但是,如果它影响渲染,并且它不在道具或状态,您会很快遇到问题,并且事情会失去同步。请参阅我的帖子。此外,还有一个想法是o解决它是否影响渲染,并且它不在道具或状态中,是订阅该变量的
此.state
。并且,只有该变量可以更新
此.state
。流程如下:
数据
->计算->
数据
此.state
。我认为我们同意。如果您没有注意到(我通常不会注意到),这个问题来自10个月前。如果您想将业务逻辑与表示状态分离,请将业务逻辑移动到容器组件,而不是组件上的实例属性。