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代碼

希望本文對大家有所幫助

有問題歡迎大家留言評論,會盡快回復的

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容