家喻户晓,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 组件之间的通信更加不便,也有利于状态的对立治理。