博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ReactNative使用Redux例子
阅读量:4056 次
发布时间:2019-05-25

本文共 7233 字,大约阅读时间需要 24 分钟。

中文文档地址:

导包:

npm install redux-thunk//这个是用来支持发送异步的action,常见如网络请求:请求前触发请求中的action,等请求拿到回调再去触发请求成功和失败的action
npm install --save react-redux
npm install --save redux

一:三个主要概念:Action、Reducer和store

store:所有的state全部在这里面,只可读,无法修改;

Reducer:页面触发不同的action来返回不同的state,他是实际操作state的;

Action:用来触发Reducer返回的,类似后台的接口

Redux的关键方法:

dispatch(ShopAction.add_goods(goods))

这个方法就是将action发送到store里面的reducer里面,store是必须唯一的,但是reducer可以是多个:

//这个表示把多个reducer连接起来,const rootReducer = combineReducers({    LoginReducer: LoginReducer,    ShopReducer:ShopReducer,});

二.react-redux

只使用Redux是不会自动帮你刷新页面的,他只是一个类似于数据服务的东西,就像后台接口,你给他什么他给你返回对应的,但是你页面展示的变更,则需要你自己来实现,所以需要state与Redux建立关系则需要React-redux。

React-Redux的关键:connect

import {connect} from 'react-redux'; // 引入connect函数

这个connect是用来将你reducer里面的的state关联你当前页面的props中的属性,从而实现动态刷新。

export default connect(    (state) => ({        status: state.LoginReducer.status,        responsedUserMessage: state.LoginReducer.responsedUserMessage,        hadAddedGoods:state.ShopReducer.hadAddedGoods,    }),    (dispatch) => ({        login: () => dispatch(LoginAction.login()),        addGoods:(goods)=>{dispatch(ShopAction.add_goods(goods))}    }))(GoodsPage)

上面的例子中,(state)表示我当前页面的props中的status即是store中的status,下面的(dispatch)表示将这个方法放到props里面,为什么不能在页面需要的地方调用dispatch({type:'type'}):(注:这里就是发送action到reducer,而action实际上是个对象。)呢,因为你在页面里面是拿不到这个dispatch对象的。最后的Frament1表示这个connect和Fragment1进行管理,如果你第二个页面也用这个reducer,那第二个页面的connect继续使用这个reducer即可

使用时调用this.props.methodName()即可。

三:适用场景:

某个页面的state会在多个页面进行关联使用,如对A页面state的增删改会影响页面B的显示

四:例子

最简单的应用场景:

以Android为例,ViewPage里面有3个Fragment,可以联想天猫。

Fragment1是用户可见的第一个页面,这个页面包含用户信息和加入购物车;

Fragment2是购物车页面,用户在Fragment1添加到购物车的需要在这里进行显示;

Fragment3是用户信息页面,如果用户在Fragment3登录了则Fragment1需要显示用户信息,否则就提示登录,而且该页面附带退出功能,退出后Fragment1的登录状态也需要改变。

分析:如果是原生开发,那么当页面重新显示的时候回调用某个方法,在这个方法对本地存储的数据进行读取展示即可。但是RN中页面重新进入并不会触发任何方法,所以这个行不通。

第一种:RN所有显示均依赖于你自己设置的state,能做的就是当Fragment1触发了加入购物车就实时更新Fragment3中的state,这里可以使用广播也可以使用导航器来传值,但是系统开销大而且不便于维护。

第二种:在global中存储你的数据,把global的数据作为显示源,也是可以的

 

使用Redux:

注:这个例子是参考以下例子:

https://github.com/NextChampion/react-native-redux-navigation-example

这个例子的源代码在

实际执行效果:

 

这里分为了二部分部分:用户是否登录以及用户信息和购物车信息

为了方便区分,我使用了两个action文件和2个reducer文件,分别对应用户和购物车。下面代码只展示用户对应的这部分

LoginTypes.js:定义登录所需的action的type信息

//这里是为了方便后期维护吧所有的type单独拉出来,直接用字符串传也无所谓//其实error和out触发的reducer是相同的,但是为了理解,分开export const LOGIN_IN = 'LOGIN_IN';export const LOGIN_IN_ERROR = 'LOGIN_IN_ERROR';export const LOGIN_OUT = 'LOGIN_OUT';

LoginAction.js:action是一个对象,必须包含‘type’字段,可以按需求添加其他字段

import * as LoginTypes from '../types/LoginTypes';//登录失败export function loginFail() {    return {        type: LoginTypes.LOGIN_IN_ERROR,    }}//登录成功export function login_in(responseData) {    return {        type: LoginTypes.LOGIN_IN,        responsedUserMessage: responseData,    }}//注销登录export function login_out() {    return {        type: LoginTypes.LOGIN_OUT    }}//如果登录过程中需要显示加载框、提示框,最好把这个操作放在所在页面,因为上传中等等是所在页面独有的state,否则处理弹出框等等很麻烦export function login() {    console.log('登录方法');    return dispatch => {        // 模拟用户登录        let result = fetch('https://www.baidu.com/')            .then((res) => {                //如果登录接口返回成功,那么把返回的json返回回去                dispatch(login_in({                    name: '小明',                    age: 12,                    image: '..',                }));            }).catch((e) => {                //如果失败,把错误返回回去。                dispatch(loginFail());            })    }}

LoginReducer.js:是个方法,在方法里面对不同的action返回不同的数据

import * as LoginTypes from "../types/LoginTypes";//这里只存储需要全局处理的数据,页面独有的state如input内容的state就在本身的页面使用。const initialState = {    status: '离线',//表示当前的登录状态,在线离线两种状态==用0和1当然更好了    responsedUserMessage: null,//登录后的用户信息}export default function LoginReducer(state=initialState, action) {    switch (action.type) {        case LoginTypes.LOGIN_IN:            return {                ...state,                status: '在线',                responsedUserMessage: action.responsedUserMessage,            }            break;        case LoginTypes.LOGIN_IN_ERROR:            return {                ...state,                status: '离线',                responsedUserMessage: null,            }            break;            case LoginTypes.LOGIN_OUT:        return {            ...state,            status: '离线',            responsedUserMessage: null,        }        break;        default:            console.log(state);            return state;    }}

Fragment1.js

'use strict';import {Provider} from 'react-redux';import React, {Component} from 'react';import {connect} from 'react-redux'; // 引入connect函数import *as LoginAction from '../actions/LoginAction'; // 引入connect函数import *as ShopAction from '../actions/ShopAction'; // 引入connect函数import {Platform, Alert,StyleSheet, Text, View, TouchableOpacity} from 'react-native';const Dimensions = require('Dimensions'); //必须要写这一行,否则报错,无法找到这个变量const ScreenWidth = Dimensions.get('window').width;const ScreenHeight = Dimensions.get('window').height;  class GoodsPage extends React.Component {    render() {        const {login}=this.props;//这是js解构赋值的写法等同于this.props.login        let bean1=  {'type':"LOGIN_IN_DOING"};        let bean=      {type:"LOGIN_IN_DOING"};        return (            
{this.props.status=="在线"?"欢迎你:"+this.props.responsedUserMessage.name:'请登录'}
{ let goods={name:'商品1:购买毫秒数'+new Date().getTime(),type:0}; this.props.addGoods(goods); }}>
添加商品1到购物车
{ let goods={name:'商品2:购买毫秒数'+new Date().getTime(),type:1}; this.props.addGoods(goods); }}>
添加商品2到购物车
); } shouldComponentUpdate(nextProps, nextState) { console.log("新的信息store里面的fragment2reducer"+JSON.stringify(nextProps.data)); // 登录完成,切成功登录 if (nextProps.status === '登陆成功' && nextProps.isSuccess) { return true; } return true; }};export default connect( (state) => ({ status: state.LoginReducer.status, responsedUserMessage: state.LoginReducer.responsedUserMessage, hadAddedGoods:state.ShopReducer.hadAddedGoods, }), (dispatch) => ({ login: () => dispatch(LoginAction.login()), addGoods:(goods)=>{dispatch(ShopAction.add_goods(goods))} }))(GoodsPage)

注意:关键点在于connect方法,我这个页面同时使用了LoginReducer和ShopReducer

RootReducer.js:将两个reducer合并

import { combineReducers } from 'redux';import LoginReducer from './LoginReducer';import ShopReducer from './ShopReducer';//这个表示把多个reducer连接起来,const rootReducer = combineReducers({    LoginReducer: LoginReducer,    ShopReducer:ShopReducer,});export default rootReducer;

 

store.js:这里是创建store的方法

import { createStore, applyMiddleware } from 'redux';import thunkMiddleware from 'redux-thunk';import rootReducer from "../../my_redux_test/reducers/RootReducer";//这里是因为使用了redux-truk的缘故,如果不用,就使用store.createStore即可const createStoreWithMiddleware = applyMiddleware(thunkMiddleware)(createStore);export default function configureStore(initialState) {    const store = createStoreWithMiddleware(rootReducer, initialState)    return store;}

 

转载地址:http://dcrci.baihongyu.com/

你可能感兴趣的文章
利用HTTP Cache来优化网站
查看>>
利用负载均衡优化和加速HTTP应用
查看>>
消息队列设计精要
查看>>
分布式缓存负载均衡负载均衡的缓存处理:虚拟节点对一致性hash的改进
查看>>
分布式存储系统设计(1)—— 系统架构
查看>>
MySQL数据库的高可用方案总结
查看>>
常用排序算法总结(一) 比较算法总结
查看>>
SSH原理与运用
查看>>
SIGN UP BEC2
查看>>
S3C2440中对LED驱动电路的理解
查看>>
《天亮了》韩红
查看>>
Windows CE下USB摄像头驱动开发(以OV511为例,附带全部源代码以及讲解) [转]
查看>>
出现( linker command failed with exit code 1)错误总结
查看>>
iOS开发中一些常见的并行处理
查看>>
iOS获取手机的Mac地址
查看>>
ios7.1发布企业证书测试包的问题
查看>>
如何自定义iOS中的控件
查看>>
iOS 开发百问
查看>>
Mac环境下svn的使用
查看>>
github简单使用教程
查看>>