本文主要是以我的另一篇文章的思維過程來操作,希望大家使用后可以記住整個過程,從而活學活用,使用到自己的項目中.
參考文章: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也是在這一步進行的)
此處代碼量較多,只粘貼關鍵代碼
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代碼
希望本文對大家有所幫助
有問題歡迎大家留言評論,會盡快回復的