React setState / Flux - 它是否总是触发重新渲染?
React setState / Flux - Does it always trigger a re-render?
我最近一直在研究 React Native,我开始对更恰当地管理我的状态感兴趣,作为在所有组件之间实现共享状态的开始。
答案当然是Flux。在继续使用一些更高级的解决方案(例如 Redux、Alt、MobX)之前,我想我应该从了解原始结构本身开始,借助一个小工具,即 Flux 调度程序。
import React, { Component } from 'react';
import { AppRegistry, Text, View } from 'react-native';
import EventEmitter from 'EventEmitter';
import { Dispatcher } from 'flux';
class Store extends EventEmitter {
list = [];
actions = {
add: title => dispatcher.dispatch({ type: 'add', payload: { title } })
};
handle = ({ type, payload }) => {
switch(type) {
case 'add': this.add(payload.title); break;
}
};
add(title) {
this.list.push(title);
this.emit('change');
}
}
const store = new Store(), dispatcher = new Dispatcher();
dispatcher.register(store.handle);
class App extends Component {
state = { list: store.list };
componentWillMount() {
this.listener = store.addListener('change', () => this.setState({ list: store.list }));
}
componentDidMount() {
setInterval(() => store.actions.add(new Date().getTime()), 1000);
}
componentWillUnmount() { this.listener.remove(); }
render() {
return (
<View style={{ marginTop: 20 }}>
<Text>{JSON.stringify(this.state.list)}</Text>
</View>
);
}
}
AppRegistry.registerComponent('straightforwardFlux', () => App);
注意在视图层,我们有{JSON.stringify(this.state.data)}
,自然地,当商店更新时,视图将被重新渲染,因为它链接到状态。
当更改为 {JSON.stringify(store.data)}
时,视图也会重新呈现!这不应该发生,因为视图只应在直接影响视图的状态发生变化时更新,在这种情况下,视图中不会呈现任何状态。我在这里错过了什么吗?为什么我们会遇到这种行为?
这又引出了另一个问题,每次状态发生变化时都会调用 render() 吗?即使它不影响视图层的外观?我对此进行了调查,得到了两个不同的答案,一个是肯定的,默认情况下 componentShouldUpdate()
returns 是真的,这意味着需要在此处进行一些更改(如果是,怎么做?),以及另一个根本没有,它不会随每个 setState()
.
更新
总的来说,这个实现是否正确?
根据 documentation...
setState() will always trigger a re-render unless conditional rendering logic is implemented in shouldComponentUpdate(). If mutable objects are being used and the logic cannot be implemented in shouldComponentUpdate(), calling setState() only when the new state differs from the previous state will avoid unnecessary re-renders.
tl;dr; React 不会分析您的视图以明确查看它所依赖的状态,这取决于您使用 shouldComponentUpdate()
进行优化。
shouldComponentUpdate(nextProps, nextState) {
// check if your view's attributes changes
let check1 = nextState.foo != this.state.foo
let check2 = nextState.bar != this.state.bar
// if return is true, the component will rerender
return check1 || check2
}
我最近一直在研究 React Native,我开始对更恰当地管理我的状态感兴趣,作为在所有组件之间实现共享状态的开始。
答案当然是Flux。在继续使用一些更高级的解决方案(例如 Redux、Alt、MobX)之前,我想我应该从了解原始结构本身开始,借助一个小工具,即 Flux 调度程序。
import React, { Component } from 'react';
import { AppRegistry, Text, View } from 'react-native';
import EventEmitter from 'EventEmitter';
import { Dispatcher } from 'flux';
class Store extends EventEmitter {
list = [];
actions = {
add: title => dispatcher.dispatch({ type: 'add', payload: { title } })
};
handle = ({ type, payload }) => {
switch(type) {
case 'add': this.add(payload.title); break;
}
};
add(title) {
this.list.push(title);
this.emit('change');
}
}
const store = new Store(), dispatcher = new Dispatcher();
dispatcher.register(store.handle);
class App extends Component {
state = { list: store.list };
componentWillMount() {
this.listener = store.addListener('change', () => this.setState({ list: store.list }));
}
componentDidMount() {
setInterval(() => store.actions.add(new Date().getTime()), 1000);
}
componentWillUnmount() { this.listener.remove(); }
render() {
return (
<View style={{ marginTop: 20 }}>
<Text>{JSON.stringify(this.state.list)}</Text>
</View>
);
}
}
AppRegistry.registerComponent('straightforwardFlux', () => App);
注意在视图层,我们有{JSON.stringify(this.state.data)}
,自然地,当商店更新时,视图将被重新渲染,因为它链接到状态。
当更改为 {JSON.stringify(store.data)}
时,视图也会重新呈现!这不应该发生,因为视图只应在直接影响视图的状态发生变化时更新,在这种情况下,视图中不会呈现任何状态。我在这里错过了什么吗?为什么我们会遇到这种行为?
这又引出了另一个问题,每次状态发生变化时都会调用 render() 吗?即使它不影响视图层的外观?我对此进行了调查,得到了两个不同的答案,一个是肯定的,默认情况下 componentShouldUpdate()
returns 是真的,这意味着需要在此处进行一些更改(如果是,怎么做?),以及另一个根本没有,它不会随每个 setState()
.
总的来说,这个实现是否正确?
根据 documentation...
setState() will always trigger a re-render unless conditional rendering logic is implemented in shouldComponentUpdate(). If mutable objects are being used and the logic cannot be implemented in shouldComponentUpdate(), calling setState() only when the new state differs from the previous state will avoid unnecessary re-renders.
tl;dr; React 不会分析您的视图以明确查看它所依赖的状态,这取决于您使用 shouldComponentUpdate()
进行优化。
shouldComponentUpdate(nextProps, nextState) {
// check if your view's attributes changes
let check1 = nextState.foo != this.state.foo
let check2 = nextState.bar != this.state.bar
// if return is true, the component will rerender
return check1 || check2
}