React的官方文件提供Immutability Helpers。
这些助手的现实使用情况是什么?我想我错过了一些非常基本的东西。
答案 0 :(得分:6)
React假设在状态中设置的对象是不可变的,这意味着如果要添加或删除数组中的某个元素,您应该创建一个带有添加元素的新元素,保持上一个数组不变:
var a = [1, 2, 3];
var b = React.addons.update(a, {'$push': [4] });
console.log(a); // [1, 2, 3];
console.log(b); // [1, 2, 3, 4];
通过使用不可变对象,您可以轻松检查对象的内容是否已更改:
React.createClass({
getInitialState: function () {
return { elements: [1, 2, 3] };
},
handleClick: function() {
var newVal = this.state.elements.length + 1;
this.setState({
elements: React.addons.update(this.state.elements, { '$push': [ newVal ] })
})
},
shouldComponentUpdate: function (nextProps, nextState) {
return this.state.elements !== nextState.elements;
},
render: function () {
return (
<div onClick={this.handleClick}>{ this.state.elements.join(', ') }</div>
);
}
});
答案 1 :(得分:2)
ReactJS状态最好是不可变。这意味着,每次调用render()
时,this.state
都应该是一个不同的对象。即:oldState == newState
为false,oldState.someProp == newState.someProp
也为false。
因此,对于简单的状态对象,毫无疑问它们应该被克隆。但是,如果您的状态对象非常复杂和深入,克隆整个状态可能会影响性能。因此,React的不变性助手很聪明,只能克隆它认为应该克隆的对象。
当您自己克隆状态时,就是这样做的:
onTextChange: function(event) {
let updatedState = _.extend({}, this.state); // this will CLONE the state. I'm using underscore just for simplicity.
updatedState.text = event.text;
this.setState(updatedState);
}
当你让React的不变性助手确定它应该实际克隆的对象时,你就是这样做的。
onTextChange: function(event) {
let updatedState = React.addons.update(this.state, { text: {$set: event.text} });
this.setState(updatedState);
}
当state
过于复杂和深刻时,上面的示例将比第一个示例更好。
答案 2 :(得分:2)
React应用程序更喜欢不变性,有两种方式(来自Facebook)支持不变性,一种是使用immutable.js这是一个完全不变的库,另一种是immutable helper,它是一个轻量级的帮助器。您只需要在一个项目中选择一个。
immutable.js的唯一缺点是它在整个应用程序中泄漏,包括商店和视图组件,例如,
// Stores
props = props.updateIn(['value', 'count'], count => count + 1);
// View Components
render: function() {
return <div>{this.props.getIn("value", "count")}</div>;
}
如果使用immutable helper,则可以将更改操作封装在更新发生的位置(例如Stores和Redux Reducers)。因此,您的View组件可以更加可重用。
// Stores or Reducers
props = update(props, {
value: {count: {$set: 7}}
};
// View Components can continue to use Plain Old JavaSript Object
render: function() {
return <div>{this.props.value.count}</div>;
}