我最近一直在玩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()
默认返回true,这意味着需要在这里进行一些更改(如果是这样,怎么做?),另一个是根本不,它不会随每个setState()
更新。
总的来说,这个实现是否正确?
答案 0 :(得分:1)
根据documentation ...
除非在shouldComponentUpdate()中实现条件呈现逻辑,否则setState()将始终触发重新呈现。如果正在使用可变对象且无法在shouldComponentUpdate()中实现逻辑,则仅当新状态与先前状态不同时调用setState()将避免不必要的重新渲染。
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
}