使用 React Native 0.21.
如何细粒度修改数据, 比如只增加数据到 state.input 中.
理想解决方法:
this.setState({name: 'Jim'}, 'input')
this.setState({Age: '24'}, 'input')
// state = {input: {name: 'Jim', Age: '24'}}
目前解决方法:
(userName) => this.setState(
function (previousState) {
return {input: Object.assign({}, previousState.input, {userName: userName})}
}
)
或许我这样想压根儿就是不对的, 当存在多层级的时候, 就应该进行组件拆分. 每个组件都是扁平的. 如果想树形结构, 那就干脆 Redux 吧.
Redux 多组件中如何 connect() 还是有点懵. 所以暂时没有使用 Redux.
1
lizheming 2016-03-11 17:32:44 +08:00
this.state.input.Age = 24;
this.forceUpdate(); |
3
leojoy710 2016-03-11 17:36:41 +08:00
替换整个 state 也没什么问题吧...redux 就是这么干的...
|
4
lizheming 2016-03-11 17:52:54 +08:00 1
@iugo 不建议的原因是因为 setState 会自动帮我们 render ,所以你在确定需要 render 的时候加上 forceUpdate 就好啦。
|
6
lizheming 2016-03-11 18:20:31 +08:00
@iugo 你自己强制渲染也是调用 React 的方法啊,为啥会有开销,而且在你有时候需要多次 this.setState 的时候(当然这种情况极少)的时候可以统一赋值完之后再 forceUpdate 更节省呢。
|
7
iugo OP @lizheming 比如在多组件中, 如果使用 forceUpdate 是否会导致所有组件都被重新渲染而不是只渲染涉及 state 变更的组件. 一个列表, 当有新的项目增加, append 新的项目而不是重新渲染整个列表.
React 应该是根据数据的变化, 有选择地进行渲染, 这样避免额外消耗吧. |
8
lizheming 2016-03-12 11:00:12 +08:00 1
@iugo 不仅仅是根据数据渲染的哦,有很多变化是不依赖 state 数据存在的,比如我这个示例中很明显的 http://codepen.io/anon/pen/vGKwQE 时间,如果按照你的理解的话,子组件不被渲染时间肯定是不变的,然而事实不是这样的。
forceUpdate 只是说当你没有更新的时候也会产生 render 而已,下面的代码可以很好的证明: https://github.com/facebook/react/blob/10f9476f3adc6658067afbf2e27c4826649f8255/src/renderers/shared/reconciler/ReactCompositeComponent.js#L646-L654 所以说其实在当你确认需要 render 的时候(你已经更改了 state 有明确的 render 需求) forceUpdate 和 setState 干的事情是一样的,不必要对性能太过担心啦。不过有一点需要注意的是,因为 forceUpdate 会强制更新,跳过 componentShouldUpdate 这个生命周期的判断,所以如果有这方面的操作的话需要确认一下。 |
9
keyanzhang 2016-06-06 15:17:26 +08:00
@lizheming 不建议您这样手动 mutate this.state 然后使用 forceUpdate 。这其实是一个 anti-pattern : this.state 这个 object 本身不会发生变化( oldState === newState ),而且像您说的一样这会跳过 shouldComponentUpdate 。换句话说就是您没有办法对是否需要 render 这件事做清晰的逻辑判断了。另外一个例子是如果 https://github.com/facebook/react/pull/6914 可以被 merge , forceUpdate 也会造成一些 heuristic 上的问题。具体您可以看 https://github.com/facebook/react/pull/6914/files#diff-748cbc3aec3f23e1ba85ea1706063ccfR178 。
|
10
lizheming 2016-06-06 15:45:32 +08:00
@keyanzhang 不好意思,那个 pull 英文太多我没看懂。。。
this.state 使用 setState 创建是 immutable 的,这个没错,如果你介意引用的问题的话那还是别直接改吧,事实上 setState 应该也是因为内部是浅拷贝的原因,所以才没办法做楼主那样的深度赋值。 另外跳过 shouldComponentUpdate 这个周期其实影响不大,因为我已经确认我的数据需要更新到视图上,那么在 this.forceUpdate() 那一刻我是非常明确需要重新 render 这个事实的,所以不存在您中间说的“无法判断是否需要 render ”。 |