React组件仅在第二个onClick事件上更改状态

Lan*_*ine 5 javascript components state reactjs

我有这两个简化的 React组件,其中Times组件是组件的子Create组件(请参阅下面的代码示例).预期的行为是,最初,Times组件未显示,但当用户单击链接时onClick,Times组件将显示.

这些组件大部分都按预期工作,但奇怪的是,在onClick第一次单击链接后,Times组件不会出现,Create组件根本不会改变状态,如控制台中所示.但是,当第二次单击链接时,Create组件会更改状态并重新呈现,并且Times可以看到组件.

Create.jsx

import React from 'react';
import Times from './Times.jsx';

export default React.createClass({

  getInitialState: function () {
    return {times: false};
  },

  _change: function () {
    this.replaceState({times: true});
    console.log(this.state.times);
  },

  render: function () {
    return (
      <div id="create">
        <div id="outerbox">
          <a onClick={this._change}>Times</a>
          <Times shouldShow={this.state.times}/>
        </div>
      </div>
    );
  }
});
Run Code Online (Sandbox Code Playgroud)

Times.jsx

import React from 'react';

export default React.createClass({

  propTypes: {
    shouldShow: React.PropTypes.bool.isRequired
  },

  getDefaultProps: function () {
    return {shouldShow: false};
  },

  getInitialState: function () {
    return {el: 'times'};
  },

  componentDidMount: function() {
    if (this.props.shouldShow === false) {
      this.setState({display: 'none'});
    } else {
      this.setState({display: 'block'});
    }
  },

  componentWillReceiveProps: function() {
    if (this.props.shouldShow === false) {
      this.setState({display: 'none'});
    } else {
      this.setState({display: 'block'});
    }
  },

  render: function () {
    return (
      <div id={this.state.el} style={{"display": this.state.display}}>
        <h1>Times</h1>
      </div>
    );
  }
});
Run Code Online (Sandbox Code Playgroud)

console.log的输出

false
true
Run Code Online (Sandbox Code Playgroud)

为什么Create第一次点击时没有注册组件的状态?

Bha*_*lli 16

问题出在这里.

 componentWillReceiveProps: function() {
    if (this.props.shouldShow === false) {
      this.setState({display: 'none'});
    } else {
      this.setState({display: 'block'});
    }
  }
Run Code Online (Sandbox Code Playgroud)

应该是哪个,

 componentWillReceiveProps: function(newProps) {
    if (newProps.shouldShow === false) {
      this.setState({display: 'none'});
    } else {
      this.setState({display: 'block'});
    }
  }
Run Code Online (Sandbox Code Playgroud)

ComponentWillRecieveProps是组件类的成员函数,在"应用"props之前调用它.这意味着this.props旧的道具.您应该使用newProps作为参数提供给函数的函数.

http://codepen.io/bhargav175/pen/gaJmKz


而且,我觉得你使用的状态比你需要的多一点.您根本不需要显示器作为状态变量.时间是一个内在的组成部分,因此尽可能多地使用道具并使它们成为无状态是有意义的.

关于"道具变化不影响渲染,所以让我们使用状态"存在一种常见的误解.道具也会在重新渲染中改变结果,所以除非有充分的理由并且你真的需要使内部组件变得聪明,否则总是使用道具.在内部组件中使用道具,使它们变得愚蠢且易于使用.

http://codepen.io/bhargav175/pen/WQBpzP

   var Times = React.createClass({

  propTypes: {
    shouldShow: React.PropTypes.bool.isRequired
  },

  getDefaultProps: function () {
    return {shouldShow: false};
  },

  getInitialState: function () {
    return {el: 'times'};
  },



  render: function () {
    let display = this.props.shouldShow ? "block" : "none";
    return (
      <div id={this.state.el} style={{"display": display}}>
        <h1>Times</h1>
      </div>
    );
  }
});
Run Code Online (Sandbox Code Playgroud)