react-native项目中从零开始使用redux

本文主要是以我的另一篇文章的思维过程来操作,希望大家使用后可以记住整个过程,从而活学活用,使用到自己的项目中.

参考文章:react-native中使用redux的原理分析及demo

demo地址:github.com/NextChampion/react-native-redux-navigation-example

react native 已更新到0.57.8版本

效果图


效果图

demo简单介绍:

功能:登录页中点击登录,跳转到主页,主页内含有一个大家都很熟悉的counter组件.可以实现简单的加减数操作;

demo逻辑:

登录:

点击登录时,组件的点击方法会发送消息到action内,

action将该消息预处理,即区分一下type,然后返回给store,

store将分好类的消息,分配到reducer中处理state.

reducer接收到带有type的消息以后,找到对应的处理办法,生成新的state返回给store,

store控制页面渲染,跳转到主页;

加减:

点击加号,组件将该点击方法发送到action内,

action预处理该消息,区分是加/减,指定type后,返回消息给store;

store收到预处理后的消息后,将该消息发送给reducer;

reducer收到store发过来的消息,根据消息内的type处理数据,真正进行加/减过程,并且将新的state返回给store;

store收到reduder发过来的新state,控制页面渲染,即页面中数字的变化;

demo特点:

1.区分登录和加减逻辑,并且将不同的state对应不同的组建部分

登录相关的state只有loginPage可用,加减相关的state只有主页面可用;

2.页面切换使用react-navigation控制;

3.该demo大家可以拿去改改部分代码,直接类比内部redux的逻辑实现过程,开发自己的项目;

下面开始详细讲解整个demo的实现过程

1.新建项目


react-native init CountersDemo

2.安装redux相关文件


npm install --save redux

npm install --save react-redux

npm install --save react-navigation

npm install --save redux-thunk

3.建立项目内部文件夹


4.redux相关代码实现过程

1)新建src文件夹存放所有js文件.

2)新建constants,actions,reducers,store,container,pages文件夹

3)(设定类型type) constans文件夹内新建文件loginType,用来划分登录过程中的事件类别


export const LOGIN_IN_DOING = 'LOGIN_IN_DOING'; //正在登陆

export const LOGIN_IN_DONE = 'LOGIN_IN_DONE'; // 登陆完成

export const LOGIN_IN_ERROR = 'LOGIN_IN_ERROR'; // 登陆出错

4.(设定预处理消息过程)actions文件夹内,新建loginAction文件,用来给预处理消息区分各个事件的类别


'use strict';

import * as types from '../constants/loginTypes';// 导入事件类型,用来做分配给各个事件

// 模拟用户信息

let user = {

name: 'zhangsan',

age: 24,

}

// 访问登录接口 根据返回结果来划分action属于哪个type,然后返回对象,给reducer处理

export function login() {

console.log('登录方法');

return dispatch => {

dispatch(isLogining()); // 正在执行登录请求

// 模拟用户登录

let result = fetch('https://www.baidu.com/')

.then((res)=>{

dispatch(loginSuccess(true,user)); // 登录请求完成

}).catch((e)=>{

dispatch(loginError(false)); // 登录请求出错

})

}

}

function isLogining() {

return {

type: types.LOGIN_IN_DOING

}

}

function loginSuccess(isSuccess, user) {

console.log('success');

return {

type: types.LOGIN_IN_DONE,

user: user,

}

}

function loginError(isSuccess) {

console.log('error');

return {

type: types.LOGIN_IN_ERROR,

}

}

5.(设定消息的具体处理过程)reducers文件夹内新建loginReducer文件,用来处理登录过程中的state变化


'use strict';

import * as types from '../constants/loginTypes'; // 导入事件类别,用来做事件类别的判断

// 初始状态

const initialState = {

status: '点击登录',

isSuccess: false,

user: null,

}

// 不同类别的事件使用switch对应处理过程

export default function loginIn(state=initialState, action) {

switch (action.type) {

case types.LOGIN_IN_DOING:

return {

...state,

status: '正在登陆',

isSuccess: false,

user: null,

}

break;

case types.LOGIN_IN_DONE:

return {

...state,

status: '登陆成功',

isSuccess: true,

user: action.user,

}

break;

case types.LOGIN_IN_ERROR:

return {

...state,

status: '登录出错',

isSuccess: true,

user: null,

}

break;

default:

return state;

}

}

6).项目内可能并不是只有一个redux操作逻辑,现在给所有的reducer建立一个统一的入口

reducers文件夹内新建index.js文件,作为统一入口;

(由于本篇文章是demo写好后整理的,所以现在这里不应该有counterReducer,大家在参考本文时,这里只写login的内容即可)


'use strict';

import { combineReducers } from 'redux';

import loginIn from './loginReducer'; // 导入登录的redux处理过程

const rootReducer = combineReducers({ // 将所有的redux处理逻辑包装在一起

loginIn: loginIn,

});

export default rootReducer; // 导出,作为统一入口

7).创建项目中的store,用来管理所有的state

store文件夹内新建ConfigureStore.js文件


'use strict';

import { createStore, applyMiddleware } from 'redux';

import thunkMiddleware from 'redux-thunk';

import rootReducer from '../reducers/index';

const createStoreWithMiddleware = applyMiddleware(thunkMiddleware)(createStore);

export default function configureStore(initialState) {

const store = createStoreWithMiddleware(rootReducer, initialState)

return store;

}

8).现在action,reducer,store都存在了,按照我另一篇原理分析内的非视图部分已基本完成.

接下来我们在处理视图部分,即Provider.在这里我个人习惯从外层往内写.先写Provider外壳,并将整个APP包裹在内;

src文件夹内,新建Root.js文件,该文件内实现Provider对视图部分的包裹


import React, { Component } from 'react';

import { Provider } from 'react-redux';

import configureStore from './store/ConfigureStore';

import App from './container/App';// app的入口

const store = configureStore();

export default class Root extends Component {  

    render() {    

        return (

            <Provider store={store}>

                <App />

           </Provider>

        ) 

    }

}

import App from './container/App';这里对应的是 app的入口 写到这里的时候,本文件还没有实现

9).实现视图的部分代码

container文件夹内新建App.js文件,作为整个app的入口;

此处使用了react-navigation用来管理页面;


import React, { Component } from 'react';

import {

View,

Text,

} from 'react-native';

import { StackNavigator } from 'react-navigation';

import LoginPage from '../pages/LoginPage'

import MainPage from '../pages/MainPage'

const App = StackNavigator({

Login: { screen: LoginPage },

Main: { screen: MainPage},

});

export default App

10.实现页面(注意此处有很关键的一步,需要在页面内实现组件和store的关联,之所以能够实现不同的组件关联不同的state也是在这一步进行的)

此处代码量较多,只粘贴关键代码


红框部分:多reducer内选择不同的reducer

class LoginPage extends Component { 

 static navigationOptions = {    title: 'LoginPage',  };  

shouldComponentUpdate(nextProps, nextState) {    

// 登录完成,切成功登录   

 if (nextProps.status === '登陆成功' && nextProps.isSuccess) {      

this.props.navigation.dispatch(resetAction)     

 return false;   

 }    

return true;  

 render() {    

const { login } = this.props;    

return(

/*...components*/

 }

}

export default connect(

(state) => ({

status: state.loginIn.status,

isSuccess: state.loginIn.isSuccess,

user: state.loginIn.user,

}),

(dispatch) => ({

login: () => dispatch(loginAction.login()),

})

)(LoginPage)

11).请大家自行实现加减法部分的逻辑并将其关联到对应的页面内.

1.设定时间的所有处理类别; type

2.事件预处理过程; action

3.事件处理过程; reducer

4.通过reducer统一入口导出供外部使用;

5.实现视图pages并将其与逻辑部分绑定到一起;connect

可查阅demo代码

希望本文对大家有所帮助

有问题欢迎大家留言评论,会尽快回复的

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容