声明:本文纯属个人学习笔记,本无意发布,参考文档注于文章结尾;
转载请注明原文地址
redux提供了一套机制来组织管理整个应用状态。
Redux有三部分组成:store,action,reducer。
store:维护全局的state,以及将action和reducer结合起来。
action:用来传递state的信息。(比如:我们在action中处理登陆操作,将返回的user对象传递给对应的reducer.)
reducer: reducer是简单的处理函数,通过传入旧的state和指示操作的action来更新state,从而达到页面的刷新。
首先安装相关库:
安装redux:npm install --save redux 安装redux绑定库:npm install --save react-redux 安装开发者工具:npm install --save-dev redux-devtools 安装异步action构造器:npm install --save redux-thunk 在集成之前熟悉下一般基于Redux的目录结构: ├── src #开发目录 | | | ├──constants #ActionTypes和Urls | | | ├──actions #actions的文件 | | | ├──components #内部组件 | | | ├──containers #容器组件 | | | ├──reducers #reducer文件 | | | ├──stores #store配置文件 | | | └──utils #工具 | ├── node_modules #包文件夹 ├── .gitignore ├── index.js #入口文件 └── package.json
- 首先创建全局的store。(一般在stores文件中写个配置文件)
import thunk from 'redux-thunk'; import {applyMiddleware, createStore}from 'redux'; import RootReducer from '../reducers/index'; const middlewares = [thunk]; const createSoreWithMiddleware=applyMiddleware(...middlewares)(createStore); //配置store信息 export default function configureStore(initialState){ const store=createSoreWithMiddleware(RootReducer,initialState); return store; }
或者这样
import thunk from 'redux-thunk'; import { createStore, applyMiddleware, compose } from 'redux'; import rootReducer from '../reducers/rootReducer'; let store = createStore(rootReducer, {}, compose( applyMiddleware(thunk), // window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() window.devToolsExtension ? window.devToolsExtension() : f => f )); export default store;
- (设定类型type) constans文件夹内新建文件actionType,用来划分事件类别
export const LOGIN_DOING = "LOGIN_DOING";//登录中 export const LOGIN_SUCCESS = "LOGIN_SUCCESS";//登录成功 export const LOGIN_ERROR = "LOGIN_ERROR";//登录失败 export const MAIN_DATA = "MAIN_DATA";//主页数据 export const MAIN_DATA_INDEX = "MAIN_DATA_INDEX";// export const MINE_DATA = "MINE_DATA";//我的页面数据
- (设定预处理消息过程)actions文件夹内,新建xxxAction文件,用来给预处理消息区分各个事件的类别(其他操作比如说数据请求等都是在这些xxxAction文件里面写逻辑代码)
// loginAction import * as types from '../../constants/actionTypes'; export function login(){ return{ type:types.LOGIN_DOING, status:'登陆中...' } } export function login2(status){ return{ type:types.LOGIN_DOING2, status } }
- (设定消息的具体处理过程)reducers文件夹内新建xxxReducer文件,用来处理对应的state的变化(数据拼接的一些操作)
import * as types from '../../constants/actionTypes'; export default function loginIn(state={ status:'请登陆'},action) { //这里的loginIn需要在总的reducer中去合并 switch(action.type){ case types.LOGIN_DOING: return{ ...state, status:'登录中...123' } break; case types.LOGIN_DOING2: return{ ...state, status:'LOGIN_DOING2' } break; default: return state; } }
- 项目内可能并不是只有一个redux操作逻辑,现在给所有的reducer建立一个统一的入口,reducers文件夹内新建index.js文件,作为统一入口;
import { combineReducers }from 'redux'; import loginIn from './loginReducer/loginReducer'; const RootReducer =combineReducers({ //应为一个app不可能只有一个reducer所以这个是用来合并所有的reducer的 loginIn, }); export default RootReducer;
- 创建项目中的store,用来管理所有的state,store文件夹内新建ConfigureStore.js文件
步骤1
- 现在action,reducer,store都存在了,接下来我们在处理视图部分,即Provider.先写Provider外壳,并将整个APP包裹在内;
src文件夹内,新建Root.js文件,该文件内实现Provider对视图部分的包裹
import React, { Component } from 'react'; import { Platform, StyleSheet, Text, View } from 'react-native'; import RootPage from './src/components/rootPage/rootPage'; import { Provider }from 'react-redux'; import configureStore from './src/stores/ConfigureStore'; import AppNavigator from './src/components/routers/AppNavigator'; const store=configureStore();// export default class App extends Component{ render() { return ( <Provider store={store}> <AppNavigator></AppNavigator> </Provider> ); } }
- 实现页面(注意此处有很关键的一步,需要在页面内实现组件和store的关联,之所以能够实现不同的组件关联不同的state也是在这一步进行的)
// import React,{ Component }from 'react'; import { View, Text, StyleSheet }from 'react-native'; import { NavigationActions }from 'react-navigation'; import * as LoginAction from '../../action/loginAction/loginAction'; import { connect} from 'react-redux'; class LoginPage extends Component{ onLogin() { const resetAction = NavigationActions.reset({ index: 0, actions: [ NavigationActions.navigate({ routeName: 'TabBar'}) ] }); this.props.navigation.dispatch(resetAction); // this.props.navigation.navigate('Work'); } render() { const {status,login,login2}=this.props;//这个必须有,是将xxxAction里面定义的方法注入进来,这样在页面中才可以使用,(有两种写法) //例如这个页面中的点击登录1和点击登录2中的onPress //还有status,初始状态在xxxAction中可以不用赋值,请看步骤3中的login2的status,在loginAction中并没有给初始值,它的初始值会来自对应的xxxReducer中的status,(这里的话可以参考步骤4的loginReducer) return ( <View style={styles.container}> <Text style={styles.instructions}> 状态:{status} </Text> <Text style={styles.welcome} onPress={()=>login()}> 点击登录1 </Text> <Text style={styles.welcome} onPress={()=>login2()}> 点击登录2 </Text> <Text onPress={()=>this.onLogin()}> 点击切换导航 </Text> </View> ); } } const styles = StyleSheet.create({这里的样式省略...}); export default connect(//写法一: (state)=>({ status:state.loginIn.status //注意看这里面的写法不一样哦,对应的上面的const {status,login,login2}=this.props;的写法也不一样呐 }), (dispatch)=>({ login:()=>dispatch(LoginAction.login()), login2:()=>dispatch(LoginAction.login2()) }) )(LoginPage);
写法二:(这是来自另一个页面的,和写法一的页面并无关联,注意⚠️这里只是展示方法) export default connect( (state) => { const {Announcement} = state; return { Announcement }; //就是这里,对应的上面的引用写法是不一样的呐,如下所示 //let {isLoad, list, refreshState} = this.props.Announcement; }, { getAnnouncementList, clearAnnouncementListContent, setAnnouncementListRefreshState } )(Announcement);
- 嗯是的基本这样就结束了哈,等我精进了再来补充哈
需要注意的几个地方:
export default connect( (state)=>({ status: state.homepage.status }), (dispatch)=>({ homepage : ()=>dispatch(mainAction.mainIndex()) }) )(Main);
在页面中的connect方法里面:state和dispatch:return的是一个纯对象
export function mainIndex(status) { return{ type:types.MAIN_DATA_INDEX, status } }
虽然xxxAction中return的status来自redux但是也要在函数里面传入参数status
const status = { status: '您已经登录了哦', user: 'Linth', account: '1314' } export default function homepage(state = status,action){ switch (action.type){ case types.MAIN_DATA_INDEX: state.status = '欢迎回来' return { ...state }; break; default: return state; } }
⚠️注意xxxReducer中return 的state前面要加上...就像上面这段代码展示的这样。
本文参考文章:
React Native集成Redux框架讲解与应用
react-native项目中从零开始使用redux