react 状态不变
by Cory House
由科里·豪斯(Cory House)设计
Perhaps the most common point of confusion in React today: state.
今天,React中最常见的混乱点是:状态。
Imagine you have a form for editing a user. It’s common to create a single change handler to handle changes to all form fields. It may look something like this:
假设您有一个用于编辑用户的表单。 创建单个更改处理程序来处理所有表单字段的更改是很常见的。 它可能看起来像这样:
updateState(event) {
const {name, value} = event.target;
let user = this.state.user; // this is a reference, not a copy...
user[name] = value; // so this mutates state ?
return this.setState({user});
}
The concern is on line 4. Line 4 actually mutates state because the user variable is a reference to state. React state should be treated as immutable.
问题在第4行上。第4行实际上是对状态进行突变,因为用户变量是对状态的引用 。 React状态应视为不可变的。
From the React docs:
从React docs :
Never mutate
this.state
directly, as callingsetState()
afterwards may replace the mutation you made. Treatthis.state
as if it were immutable.切勿直接
this.state
,因为之后调用setState()
可能会替换您所做的this.state
。this.state
视为不可变的。
Why?
为什么?
- setState batches work behind the scenes. This means a manual state mutation may be overridden when setState is processed. setState批处理在后台进行。 这意味着在处理setState时可以覆盖手动状态突变。
If you declare a shouldComponentUpdate method, you can’t use a === equality check inside because the object reference will not change. So the approach above has a potential performance impact as well.
如果声明了shouldComponentUpdate方法,则不能在内部使用===相等检查,因为对象引用不会更改 。 因此,上述方法也可能会对性能产生影响。
Bottom line: The example above often works okay, but to avoid edge cases, treat state as immutable.
底线 :上面的示例通常可以正常工作,但要避免出现极端情况,请将状态视为不可变的。
Here are four ways to treat state as immutable:
以下是将状态视为不可变的四种方法:
方法1:Object.assign (Approach 1: Object.assign)
Object.assign creates a copy of an object. The first parameter is the target, then you specify one or more parameters for properties you’d like to tack on. So fixing the example above involves a simple change to line 3:
Object.assign创建对象的副本。 第一个参数是目标,然后为要添加的属性指定一个或多个参数。 因此,修复上面的示例涉及对第3行的简单更改:
updateState(event) {
const {name, value} = event.target;
let user = Object.assign({}, this.state.user);
user[name] = value;
return this.setState({user});
}
On line 3, I’m saying “Create a new empty object and add all the properties on this.state.user to it.” This creates a separate copy of the user object that’s stored in state. Now I’m safe to mutate the user object on line 4 — it’s a completely separate object from the object in state.
在第3行中,我说的是“创建一个新的空对象,并将this.state.user上的所有属性添加到其中。” 这将创建状态存储的用户对象的单独副本。 现在,我可以安全地更改第4行上的用户对象-它是与处于状态状态的对象完全独立的对象。
Be sure to polyfill Object.assign since it’s unsupported in IE and not transpiled by Babel. Four options to consider:
请确保pol