evantianx / Bloooooooog

Place to record what I thought and learned
0 stars 0 forks source link

【译】Handling State in React: Four Immutable Approaches to Consider #45

Open evantianx opened 7 years ago

evantianx commented 7 years ago

原文链接

evantianx commented 7 years ago

Never mutate this.state directly, as calling setState() afterwards may replace the mutation you made. Treat this.state as if it were immutable.

// 很危险的做法 ⚠️
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});
}

Object.assign()

updateState(event) {
 const {name, value} = event.target;
 // 创建一个空对象并将 state.user 中所有属性赋予
 let user = Object.assign({}, this.state.user);
 user[name] = value;
 return this.setState({user});
}

这个方法的弊端在于——对低级浏览器兼容性不好: 关于它的 polyfill 可以在 polyfill.io 或者 MDN上查看

对象展开符

updateState(event) {
 const {name, value} = event.target;
 let user = {...this.state.user, [name]: value};
 this.setState({user});
}

更为简洁:

updateState({target}) {
 this.setState({user: {...this.state.user, [target.name]: target.value}});
}

Immutability Helper

官方提供Immutability Helpers也可以实现

import update from 'immutability-helper';

updateState({target}) {
 let user = update(this.state.user, {$merge: {[target.name]: target.value}});
 this.setState({user});
}

注意:这个merge方法只能提供浅复制

更多 immutability Helper 的用法参见 immutability-helper Github

Immutable.js

import { Map } from 'immutable';

// Later, in constructor...
this.state = {
  // Create an immutable map in state using immutable.js
  user: Map({ firstName: 'Cory', lastName: 'House'})
};

updateState({target}) {
 // this line returns a new user object assuming an immutable map is stored in state.
 let user = this.state.user.set(target.name, target.value);
 this.setState({user});
}

缺点在于 Immutable.js 体积过大,且语法不是很贴切。