家喻户晓,React中数据通信是单向的,即父组件能够通过props向子组件传递数据,而子组件却不能向父组件传递数据。要实现子组件向父组件传递数据的需要,须要父组件提供一个批改数据的办法,当页面越来越多的时候,数据的治理就会变得异样简单。
并且,每次数据的更新都须要调用setState,特地是波及到跨组件通信的问题就会很麻烦。在React开发中,为了解决跨组件通信的问题,业界开发了一大批状态治理框架,目前比拟罕用的React状态治理框架有Flux、Redux和Mobx等几个。
其中,Flux是Facebook用于建设客户端Web利用的前端架构,它利用一个单向数据流的形式补充了React的组合视图组件,解决了MVC技术架构中数据流管理混乱的问题。Redux则是由Dan Abramov开源的一款前端状态治理框架,Redux框架由Action、Store和Reducers三局部组成,所有组件的数据都存储到Store对象中,每个组件只须要扭转Store中的数据,当Store数据发生变化时就会其余订阅的组件执行数据更新。Mobx是一个面向对象的状态治理框架,它与Redux的最大区别是能够间接批改数据,精准的告诉UI进行刷新,而不是Redux的播送。
能够发现,Redux特地适宜用在须要集中式治理数据场景中。多个组件应用同一个数据源,保护同一个数据样本,进而放弃各个组件之间数据的一致性。react-redux是Redux状态框架在React中的技术实现,对于相熟Redux状态治理框架开发者来说,学习react-redux将会显得非常容易。
在Redux状态框架中,Redux将状态治理分为Action、Store和Reducers三局部。其中,Redux将应用程序的状态存储到Store中,组件通过dispatch()办法触发Action,Store接管Action并将Action转发给Reducer,Reducer依据Action类型对状态数据进行解决并将处理结果返回给Store,其余组件通过订阅Store状态的来刷新本身的状态,整个框架的工作流程如图3-9所示。
上面以计数器为例来阐明Redux的根本应用。首先,创立一个action.js文件,用来寄存Action行为事件,如下所示。
export const ADD = 'ADD'export const MINUS = 'MINUS'
而后,创立一个reducer.js文件,用来解决业务逻辑的更新,并将解决的后果返回给Store,如下所示。
import {ADD, MINUS} from './action';function reducer (state = {count: 0}, action) { switch(action.type) { case ADD: return {count: state.count + 1} case MINUS: return {count: state.count - 1} default: return state }}export default reducer;
Reducer是一个纯函数,接管State和Action两个参数。其中,State是旧的状态,不能够间接批改,Reducer会依据Action的类型来生成不同的新State,并将后果返回给Store。
接下来,创立一个全局的Store对象,用来寄存利用的状态数据,创立时须要应用Store提供的createStore()办法,如下所示。
import { createStore } from 'redux'import reducer from './reducer';const store = createStore(reducer)export default store
除了createStore()办法外,创立的Store还有以下几个办法能够调用。
- getState():获取最新的状态数据。
- dispatch():派发Action行为事件。
- subscribe():订阅Store中的状态变动。
为了实现计数器加减的性能,还须要在组件的生命周期函数中增加订阅事件,并在组件销毁时解决订阅,如下所示。
class CounterPage extends React.Component { constructor(props){ super(props) this.state = { number: store.getState().count } } componentDidMount () { this.unSubscribe = store.subscribe(() => { this.setState({ number: store.getState().count }) }) } componentWillUnmount () { this.unSubscribe && this.unSubscribe() } render() { return ( <View style={styles.ct}> <Text>{this.state.number}</Text> <Button title="加1" onPress={() => store.dispatch({type: 'ADD'})}/> <Button title="减1" onPress={() => store.dispatch({type: 'MINUS'})}/> </View> ); }}const styles = StyleSheet.create({ ct: { flex: 1, justifyContent: 'center', alignItems: 'center', },});export default CounterPage;
在下面的代码中,咱们通过store.getState()办法来获取最新的State,而执行加减操作时通过store.dispatch()办法派发Action给Store。能够发现,在类组件中应用Redux还是挺繁琐的,须要开发者本人治理组件的状态数据,而如果改用React Hook就要简略许多。
在React Hook中应用Redux须要应用react-redux库提供的useSelector()与useDispatch()两个函数。其中,useSelector()函数能够用来获取状态值,而useDispatch()则能够用来批改状态数据,如下所示。
import { useSelector, useDispatch } from 'react-redux'const CounterPage = () => { const count = useSelector(state => state.count) const dispatch = useDispatch() return ( <View style={styles.ct}> <Text>{count}</Text> <Button title='加1' onPress={() => dispatch({type: 'ADD'})}/> <Button title='减1' onPress={() => dispatch({type: 'MINUS'})}/> </View> );}const styles = StyleSheet.create({ …. //省略代码});export default CounterPage
能够发现,相比于类组件来说,应用React Hook实现就要简洁许多。首先,咱们应用useSelector()函数获取Store中的状态,而后再应用useDispatch()函数派发事件。
最初,应用Redux在让不同组件之间共享状态数据时,还须要应用react-redux库提供的Provider包裹利用组件,如下所示。
const App = () => { return ( <Provider store={store}> <CounterPage /> </Provider> );};
从新运行代码,就实现了计数器的性能,如下图所示。
最初,须要阐明的是,应用Redux进行状态治理时,应留神以下几点:
• 利用中有且仅有一个Store,该Store存储了整个利用的状态。
• State是只读的,批改State只能通过派发Action事件,为了形容Action扭转State的过程,须要应用Reducer纯函数。
• 繁多数据源让多个React组件之间的通信更加不便,也有利于状态的对立治理。