属性更改时更改状态并首次挂载React - Missing函数?

时间:2015-04-01 18:01:50

标签: reactjs

我遇到了基于属性的状态问题。

场景

我有一个Component父级,它创建一个属性传递给子组件。 子组件根据收到的属性做出反应。 在React中只有"只有"改变组件状态的正确方法是使用函数componentWillMount或componentDidMount和componentWillReceiveProps到目前为止(除其他之外,但让我们关注这些,因为getInitialState只执行一次)。

我的问题/问题

如果我从父级接收新属性并且我想要更改状态,则只会执行函数componentWillReceiveProps并允许我执行setState。渲染不允许setStatus。

如果我想在开头设置状态以及收到新属性的时间怎么办? 所以我必须在getInitialState或componentWillMount / componentDidMount上设置它。然后,您必须使用componentWillReceiveProps根据属性更改状态。

当你的州高度依赖你的财产时,这是一个问题,这几乎总是如此。这可能变得愚蠢,因为你必须根据新属性重复你想要更新的状态。

我的解决方案

我创建了一个新方法,它在componentWillMount和componentWillReceiveProps上调用。我没有找到在渲染之前更新属性之后调用的任何方法,也是第一次安装Component时。然后就没有必要做这个愚蠢的解决方法。

无论如何,这里的问题是:在收到或更改新房产时,是否有更好的选项来更新状态?

/*...*/
/**
 * To be called before mounted and before updating props
 * @param props
 */
prepareComponentState: function (props) {
    var usedProps = props || this.props;

    //set data on state/template
    var currentResponses = this.state.candidatesResponses.filter(function (elem) {
        return elem.questionId === usedProps.currentQuestion.id;
    });
    this.setState({
        currentResponses: currentResponses,
        activeAnswer: null
    });
},
componentWillMount: function () {
    this.prepareComponentState();
},
componentWillReceiveProps: function (nextProps) {
    this.prepareComponentState(nextProps);
},
/*...*/

我觉得有点傻,我想我失去了一些东西...... 我想还有另一种解决方案可以解决这个问题。

是的,我已经知道了这件事: https://facebook.github.io/react/tips/props-in-getInitialState-as-anti-pattern.html

1 个答案:

答案 0 :(得分:23)

我发现这种模式通常不是很必要。 在一般情况下(并非总是如此),我发现根据已更改的属性设置状态有点像反模式;相反,只需在渲染时派生必要的本地状态。

render: function() {
  var currentResponses = this.state.candidatesResponses.filter(function (elem) {
    return elem.questionId === this.props.currentQuestion.id;
  });

  return ...; // use currentResponses instead of this.state.currentResponses
}

但是,在某些情况下,缓存此数据是有意义的(例如,计算它可能非常昂贵),或者您只需要知道道具何时因其他原因而设置/更改。在这种情况下,我会基本上使用你在问题中写过的模式。

如果您确实不想输入它,您可以将这种新方法正式化为mixin。例如:

var PropsSetOrChangeMixin = {
  componentWillMount: function() {
    this.onPropsSetOrChange(this.props);
  },

  componentWillReceiveProps: function(nextProps) {
    this.onPropsSetOrChange(nextProps);
  }
};

React.createClass({
  mixins: [PropsSetOrChangeMixin],

  onPropsSetOrChange: function(props) {
    var currentResponses = this.state.candidatesResponses.filter(function (elem) {
        return elem.questionId === props.currentQuestion.id;
    });

    this.setState({
      currentResponses: currentResponses,
      activeAnswer: null
    });
  },

  // ...
});

当然,如果你使用基于class的React组件,你需要找到一些替代解决方案(例如继承或自定义JS mixins),因为他们不会立即获得React风格的mixins。

(对于它的价值,我认为使用显式方法代码更清晰;我可能会这样写:)

componentWillMount: function () {
  this.prepareComponentState(this.props);
},

componentWillReceiveProps: function (nextProps) {
  this.prepareComponentState(nextProps);
},

prepareComponentState: function (props) {
  //set data on state/template
  var currentResponses = this.state.candidatesResponses.filter(function (elem) {
    return elem.questionId === props.currentQuestion.id;
  });
  this.setState({
    currentResponses: currentResponses,
    activeAnswer: null
  });
},