我遇到了基于属性的状态问题。
我有一个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
答案 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
});
},