当属性更改并首次挂载 React 时更改状态 - 缺少功能? [英] Change state when properties change and first mount on React - Missing function?

查看:34
本文介绍了当属性更改并首次挂载 React 时更改状态 - 缺少功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一个关于基于属性的状态的问题.

I have come across a problem about states based on properties.

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

I have a Component parent which creates passes a property to a child component. The Child component reacts according to the property received. In React the "only" proper way to change the state of a component is using the functions componentWillMount or componentDidMount and componentWillReceiveProps as far as I've seen (among others, but let's focus on these ones, because getInitialState is just executed once).

如果我从父级收到一个新属性并且我想更改状态,则只会执行函数 componentWillReceiveProps 并允许我执行 setState.Render 不允许设置状态.

If I receive a new property from the parent and I want to change the state, only the function componentWillReceiveProps will be executed and will allowed me to execute setState. Render does not allow to setStatus.

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

What if I want to set the state on the beginning and the time it receives a new property? So I have to set it on getInitialState or componentWillMount/componentDidMount. Then you have to change the state depending on the properties using componentWillReceiveProps.

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

This is a problem when your state highly depends from your properties, which is almost always. Which can become silly because you have to repeat the states you want to update according to the new property.

我创建了一个在 componentWillMount 和 componentWillReceiveProps 上调用的新方法.我没有发现在渲染之前更新属性后以及第一次安装组件后调用任何方法.那么就没有必要做这种愚蠢的解决方法了.

I have created a new method that it's called on componentWillMount and on componentWillReceiveProps. I have not found any method been called after a property has been updated before render and also the first time the Component is mounted. Then there would not be a need to do this silly workaround.

无论如何,这里的问题是:当收到或更改新属性时,没有更好的选择来更新状态吗?

Anyway, here the question: is not there any better option to update the state when a new property is received or changed?

/*...*/
/**
 * 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);
},
/*...*/

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

I feel a bit stupid, I guess I'm loosing something... I guess there is another solution to solve this.

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

推荐答案

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

I've found that this pattern is usually not very necessary. In the general case (not always), I've found that setting state based on changed properties is a bit of an anti-pattern; instead, simply derive the necessary local state at render time.

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
}

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

However, in some cases, it can make sense to cache this data (e.g. maybe calculating it is prohibitively expensive), or you just need to know when the props are set/changed for some other reason. In that case, I would use basically the pattern you've written in your question.

如果你真的不喜欢输入它,你可以将这个新方法形式化为 mixin.例如:

If you really don't like typing it out, you could formalize this new method as a mixin. For example:

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-立即混合样式.

Of course, if you're using class-based React components, you'd need to find some alternative solution (e.g. inheritance, or custom JS mixins) since they don't get React-style mixins right now.

(就其价值而言,我认为使用显式方法使代码更清晰;我可能会这样写:)

(For what it's worth, I think the code is much clearer using the explicit methods; I'd probably write it like this:)

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
  });
},

这篇关于当属性更改并首次挂载 React 时更改状态 - 缺少功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆