在react-native开发中关于数据的流向,state的管理及路由解决等问题会随着项目的复杂让人越来越头疼,也让人力不从心。于是React的开发者推出了Flux架构及官方实现,力图解决这些问题。Flux框架其核心思想就是单项数据流,Flux的整个流程为:Action -> Dispatcher -> Store -> View.
当然Flux框架只是一种单向数据流的思想,业界有很多基于Flux的框架,当下最流行的当属Redux。
Redux的三大定律:1.单一数据源。2.state是只读的,改变state的唯一方法就是触发action,action其实就是一个普通的javascript对象。3.使用纯函数执行修改,这里所说的纯函数就是Redux中reducer。
Redux的组成:
1.action
首先要知道action就是一个信息载体,也是一个javascript对象,对象中至少要包括一个动作行为的唯一标示,比如增删改查操作。
比如:
userAction.js
- import * as constant from '../constants/CommonConstants';
- export function updateData(user){
- return {
- type: constant.UPDATE_DATA,user: user
- };
- }
- export function requestData(){
- return dispatch => {
- let url = 'https://my.oschina.net/gef';
- fetch(url)
- .then((response) =>{
- console.log("response:" + response);
- return response.text();
- })
- .then((responseText) => {
- console.log("responseText:" + responseText);
- if (responseText) {
- let user = {
- 'name' : "葛夫锋",'age' : 18,'job' :'developer'
- };
- dispatch(updateData(user));
- }
- })
- .catch((error) => {
- console.log("error:" + error);
- });
- };
- }
我定义了两个action,第一个是更新数据的action,第二个是请求数据的action,第二个action所return的其实是一个函数,其参数为dispatch,然后进行了网络请求,请求成功之后执行了第一个action。
2.reducer
action定义了要执行的操作,但是没有规定action执行之后state如何变化,那么reducer的任务就是定义整个程序的state如何响应。
其实reducer就是一个纯函数,例如:
UserReducer.js
- import * as constant from '../constants/CommonConstants'
- const initState = {
- flag:1,//1请求中 2请求成功
- user: null
- }
- export default function addUser(state = initState,action){
- switch(action.type){
- case constant.LOAD_USER:
- return Object.assign({},state,{flag : 1});
- case constant.UPDATE_DATA:
- return Object.assign({},{flag : 2,user : action.user});
- default:
- return state;
- }
- }
baseReducers.js
- import {combineReducers} from 'redux';
- import UserReducer from './UserReducer';
- const rootReducer = combineReducers({
- UserReducer
- });
- export default rootReducer;
- 保存整个程序的state@H_502_48@
- 通过getState()方法访问state的值@H_502_48@
- 通过dispatch()方法执行一个action@H_502_48@
- 通过subscribe(listener)注册回调,监听state的变化@H_502_48@
例如:
index.ios.js
- /**
- * Sample React Native App
- * https://github.com/facebook/react-native
- * @flow
- */
- import {
- AppRegistry,} from 'react-native';
- import React from 'react';
- import {applyMiddleware,createStore} from 'redux';
- import thunk from 'redux-thunk';
- import {Provider} from 'react-redux';
- import Root from './app/root';
- import rootReducers from './app/reducers/baseReducers';
- var store = createStore(rootReducers,applyMiddleware(thunk));
- function App(props){
- return (
- <Provider store = {store}>
- <Root {...this.props}/>
- </Provider>
- );
- };
- AppRegistry.registerComponent('ReduxDemo',() => App);
root.js
- import React from 'react';
- import {View,StyleSheet,Text} from 'react-native';
- import {connect} from 'react-redux';
- import {requestData,updateData2} from './actions/userAction';
- class Root extends React.Component{
- render(){
- let {flag,user} = this.props;
- //flag
- let content = null;
- if(flag == 1){
- content = (<Text>加载中</Text>);
- }else{
- content = (<Text>加载成功</Text>);
- }
- //user
- let userView = null;
- if (user) {
- userView = (<View style = {style.userView}>
- <Text>姓名:{user.name}</Text>
- <Text>年龄:{user.age}</Text>
- <Text>工作:{user.job}</Text>
- </View>);
- }
- return (
- <View style = {style.container}>
- {content}
- {userView}
- </View>
- );
- }
- componentDidMount(){
- let {updateData} = this.props;
- updateData();
- }
- }
- const style = StyleSheet.create({
- container:{
- flex: 1,alignItems: 'center',justifyContent:'center',backgroundColor: '#FF6A6A'
- },userView:{
- marginTop:10
- }
- });
- function mapStateToProps(state){
- return {
- flag:state.UserReducer.flag,user:state.UserReducer.user
- };
- }
- function mapDispatchToProps(dispatch){
- return {
- updateData:function(){
- dispatch(requestData());
- }
- };
- }
- export default connect(mapStateToProps,mapDispatchToProps)(Root);
这里用到了react-redux库,用于辅助在React项目中使用Redux,它的API相当简单,包括一个React Component(Provider)和一个高阶方法connect。
这里还用到了一个middleware,叫做redux-thunk。redux-thunk的存在允许 store.dispatch一个函数,也就是action不是一个javascript对象,而可以是一个函数。
以上代码例子组合起来就是一个网络异步加载的小例子,其运行效果如下:
完整代码:
https://github.com/johngef/Redux-Demo