为什么this.setState没有更新this.states?

时间:2017-01-21 16:07:31

标签: javascript reactjs

在我的代码中this.setState似乎没有更新this.states,但会触发重新渲染。 componentWillUpdate回调也显示正确的参数。

class TimeButton extends React.Component {
  constructor(){
    super();
    this.states = {
      percentage : 50
    }
  }
  componentWillUpdate(nextProps, nextState){
    console.log("componentWillUpdate currentstate")
    console.log(this.states);
    console.log("componentWillUpdate nextstate")
    console.log(nextState);

  }

  componentDidMount(){
    let component = this;
    console.log("componentDidMount");
    console.log(this.states);

    this.setState({
      percentage : 70,
      test : 10101010
    }, () => {
      console.log("callback setState");
      console.log(this.states);
    })

  }

  componentWillUnmount(){
  }

  handleClick(){
    this.props.onClick(component.props);
  }

  render(){
    console.log("render");
    console.log(this.states);
    let component = this;
    let { buttonInnerRadius, buttonOuterRadius, x, y } = this.props
    return (
      <Group onClick={component.handleClick.bind(component)}>
        <CircularBar x={x} y={y} innerRadius={buttonInnerRadius} outerRadius={buttonOuterRadius} ref="bar" percentage={this.states.percentage}></CircularBar>
        <Circle x={x} y={y} radius={buttonOuterRadius}></Circle>
      </Group>
    )
  }
}

所以这是结果

my program's output

我在这里做错了吗? setState在我编码的其他地方之前已经工作了

如果我做蠢事如

this.states.percentage = 70
this.states.test = 101010
this.forceUpdate()

它运作得很好,但这看起来不错

到目前为止,我已经检查了

Why is my setState is not working? [duplicate]

Why is 'this.setState' not working?

2 个答案:

答案 0 :(得分:2)

这只是代码中的拼写错误。组件的状态称为state,而不是states

答案 1 :(得分:1)

@Tholle是精确的,this.state存在于React类模块中。没有像this.states

那样的东西
/**
 * Module for creating composite components.
 *
 * @class ReactClass
 */
var ReactClass = {

  createClass: function(spec) {
    // To keep our warnings more understandable, we'll use a little hack here to
    // ensure that Constructor.name !== 'Constructor'. This makes sure we don't
    // unnecessarily identify a class without displayName as 'Constructor'.
    var Constructor = identity(function(props, context, updater) {
      // This constructor gets overridden by mocks. The argument is used
      // by mocks to assert on what gets mounted.

      if (__DEV__) {
        warning(
          this instanceof Constructor,
          'Something is calling a React component directly. Use a factory or ' +
          'JSX instead. See: https://facebook.github.io/react/warnings/legacy-factories.html'
        );
      }

      // Wire up auto-binding
      if (this.__reactAutoBindPairs.length) {
        bindAutoBindMethods(this);
      }

      this.props = props;
      this.context = context;
      this.refs = emptyObject;
      this.updater = updater || ReactNoopUpdateQueue;

      this.state = null;

您可以通过 this.state 方法将setState 所需的任何放入其中。在这里,我将状态a设置为值'a'

 this.setState({ a: 'a' });
  

如果我做蠢事如

this.states.percentage = 70
this.states.test = 101010
this.forceUpdate()

这将动态添加states属性。但是,这并不聪明。

应始终使用setState方法设置状态,即使您改善输入错误,也不要直接设置状态。这应该像这里所解释的那样异步完成。

File: react/docs/js/react.js
1220: /**
1221:  * Sets a subset of the state. Always use this to mutate
1222:  * state. You should treat `this.state` as immutable.
1223:  *
1224:  * There is no guarantee that `this.state` will be immediately updated, so
1225:  * accessing `this.state` after calling this method may return the old value.
1226:  *
1227:  * There is no guarantee that calls to `setState` will run synchronously,
1228:  * as they may eventually be batched together.  You can provide an optional
1229:  * callback that will be executed when the call to setState is actually
1230:  * completed.
1231:  *
1232:  * When a function is provided to setState, it will be called at some point in
1233:  * the future (not synchronously). It will be called with the up to date
1234:  * component arguments (state, props, context). These values can be different
1235:  * from this.* because your function may be called after receiveProps but before
1236:  * shouldComponentUpdate, and this new state, props, and context will not yet be
1237:  * assigned to this.
1238:  *
1239:  * @param {object|function} partialState Next partial state or function to
1240:  *        produce next partial state to be merged with current state.
1241:  * @param {?function} callback Called after state is updated.
1242:  * @final
1243:  * @protected
1244:  */
1245: ReactComponent.prototype.setState = function (partialState, callback) {
1246:   !(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null) ? "development" !== 'production' ? invariant(false, 'setState(...): takes an object of state variables to update or a function which returns an object of state variables.') : _prodInvariant('85') : void 0;
1247:   this.updater.enqueueSetState(this, partialState);
1248:   if (callback) {
1249:     this.updater.enqueueCallback(this, callback, 'setState');
1250:   }
1251: };

正如here所述: 唯一可以指定this.state的地方是构造函数。

直接设置状态不会重新渲染组件,这应该是setState()方法背后的想法。

此外,React可以将多个setState()次调用批量处理为单个更新以提高性能。