为什么我的React组件不能在setState()上重新渲染?

时间:2016-07-13 19:41:39

标签: javascript reactjs

我有以下代码(简化,简单,简单)。我希望我的Submission组件在单独单击(工作)或按下按钮以显示所有这些(不起作用)时显示作者。

我已经确认单击按钮时正在更改SubmissionList状态,并且正在正确设置提交的初始状态,那么为什么setState更改不会过滤到提交?

我确定我错过了什么,所以任何帮助都会受到赞赏。谢谢!

let Submission = React.createClass({
  getInitialState: function() {
    return {
      showAuthor: this.props.revealed
    };
  },

  reveal: function() {
    this.setState({
      showAuthor: !this.state.showAuthor
    });
  },

  render: function() {
    let authorText;
    if (this.state.showAuthor) {
      authorText = " - " + this.props.author;
    } else {
      authorText = "";
    }

    return (
      <li className="submission" onClick={this.reveal}>
        <span className="submissionText">
          {this.props.text}
        </span>
        <span className="submissionAuthor">
          {authorText}
        </span>
      </li>
    );
  }
});

let SubmissionList = React.createClass({
  getInitialState: function() {
    return {
      revealAll: true
    };
  },

  revealAllSubmissions: function() {
    this.setState({
      revealAll: !this.state.revealAll
    });
  },

  render: function() {
    let revealed = this.state.revealAll;
    let submissionNodes = this.props.data.map(function(submission) {
      return (
        <Submission author={submission.author} key={submission.id} text={submission.text} revealed={revealed} />
      );
    });

    return (
      <div className="allSubmissions">
        <button onClick={this.revealAllSubmissions}>Reveal All</button>
        <ul className="submissionList">
          {submissionNodes}
        </ul>
      </div>
    );
  }
});
编辑:实际上看不到我的标签写在段落中。为清晰起见,已更新。

1 个答案:

答案 0 :(得分:1)

如果您希望两个组件都具有内部状态,则需要将componentWillReceiveProps处理程序添加到Submission。并同步道具也在那里陈述。

let Submission = React.createClass({
  getInitialState: function() {
    return {
      showAuthor: this.props.revealed
    };
  },
  componentWillReceiveProps: function(nextProps) {
     if(this.props.revealed !== nextProps.revealed) {
        this.setState({
           showAuthor: nextProps.revealed
        });
     }
  },
  ...

但正如您所看到的,这会导致代码重复。从现在开始你有2个状态源(道具和内部组件状态)。更好的想法是将状态移动到父组件并使Submission成为代表组件(没有内部状态)

let Submission = ({showAuthor, author, toggle, text}) => (
  <li className="submission" onClick={toggle}>
    <span className="submissionText">
      {text}
    </span>
    <span className="submissionAuthor">
      {showAuthor ? `-${author}` : null}
    </span>
  </li>
)

其中toggle是一个将当前提交的showAuthor切换为SubmissionList状态的函数。

UPD 您可以传递仅切换当前提交的特定切换。例如

let submissionNodes = this.props.data.map(function(submission) {
  return (
    <Submission
      author={submission.author}
      key={submission.id} 
      text={submission.text}
      toggle={() => this.toggleSubmissionById(submission.id)} />
  );
})