1. 程式人生 > >React Native整合Redux框架講解與應用

React Native整合Redux框架講解與應用

          學過React Native的都知道,RN的UI是根據相應元件的state進行render的,而頁面又是由大大小小的元件構成,導致每個元件都必須維護自身的一套狀態,因此當頁面複雜化的時候,管理state會相當吃力的。而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

如果你之前不瞭解Redux的話,或許會比較蒙圈,但不要緊,跟著流程多走幾遍,試著推敲先分析下流程,慢慢就理解了

/*************************************store*************************************/

1.首先建立全域性的store。(一般在stores檔案中寫個配置檔案)

'use strict';

import { createStore, applyMiddleware ,combineReducers} from 'redux';
import thunk from 'redux-thunk';//引入非同步操作
//引入所有的reducers,切記要在index.js封裝下.
import * as reducers from '../reducers';
const middlewares = [thunk];

const createSoreWithMiddleware=applyMiddleware(...middlewares)(createStore);

//配置store資訊
export default function configureStore(initialState){

  //將reducer組合起來
  const reducer=combineReducers(reducers);
  //建立store
  const store=createSoreWithMiddleware(reducer,initialState);
  
  return store;
}

簡單講解下:

首先引入該APP中所有的reducer,根據上面的目錄結構,我們把所有的reducer放入到reducers檔案中,切記要加入個index.js進行配置.上面很多都是固定格式,暫時先不分析為什麼,做的目的就是返回一個全域性的store.

store的應用這裡的APP就是我們應用的最頂層元件)。

import React, { Component } from 'react';
import {Provider} from 'react-redux';
import App from './containers/app';

import configureStore from './store/configureStore';
const store=configureStore();//獲取store

export default class Root extends Component{
   render(){
     return(
       <Provider store={store}>
       <App/>
       </Provider>
     );
   }
}

App元件其實可以把所有的頁面加入到這裡,全域性進行控制(官方F8是這麼操作的)。不過這裡暫時先不這樣處理,關於navigator的push,pop操作還是放到對應的頁面進行處理,更符合我們的原生開發邏輯。

簡單看下store中結構:


/*************************************action*************************************/

建立登陸對應的action:

 import * as types from './types';
 import {Alert}from 'react-native';

//登陸(登陸操作屬於耗時操作,所以需要非同步執行,這裡採用dispatch分發)
export function login(user){
   return dispatch=>{
     //登陸中,派遣給LOGIN_ING
     dispatch({type:types.LOGIN_ING});
     let result=fetch('http://www.baidu.com')
                .then((res)=>{
                  //延時2s為了模擬效果
                  setTimeout(()=>{
                    if(user.phone=='15221850400'&&user.password=='123456'){
                      dispatch({type:types.LOGIN,user:user});
                    }else{
                      //這裡分發的是action
                      Alert.alert('使用者名稱或密碼錯誤');

                      dispatch(error());
                    }
                  },1000);
                }).catch((err)=>{
                   alert(err);
                   dispatch({type:types.LOGIN_ERROR});
                })
   }
}

function error(){
  return {
    type:types.LOGIN_ERROR
  };
}

//登出(由於登出操作一般都只是清空一些資料,不需要非同步執行直接返回就可以了,)
export function logout(){
  return {
    type:types.LOGOUT,
  };
}

邏輯還算簡單,就只是做個使用者名稱,密碼判斷,但或許會問dispatch是個什麼玩意,哪來的呢,其實上面我們也截圖出來了,這個方法是我們建立全域性store中的方法。

至於action正常的應該只是一個含有type的json物件,但是為了擴充套件性,一般會寫成函式的形式,俗稱action creator如上面的logout方法.

至於login方法由於需要網路操作,固然是非同步的,就好比我們原生開發的時候請求API的操作一般都會丟到一個執行緒中,通過Handler訊息機制來渲染UI.

dispatch({type:types.LOGIN_ING}):根據相應的action來進行呼叫對應reducer方法。

/*************************************reducer*************************************/

接著我們看下最後一個reducer:

import * as types from '../actions/types';

const initialState={
  isLoggedIn:false,//登陸狀態
  user:{},
  status: null,//登陸操作狀態 ‘done’:已登陸,'doing':正在登陸,null:沒有登陸
};

//reducer處理函式更新state,渲染UI(主要根據傳入舊的state,)
export default function user(state=initialState,action={}){

  switch(action.type) {
    case types.LOGIN:
       return{
         ...state,
         isLoggedIn:true,
         user:action.user,
         status: 'done',
       }
      break;
    case types.LOGIN_ING:
      return {
        ...state,
        isLoggedIn:false,
        status: 'doing',
      }
      break;
    case types.LOGIN_ERROR:
    console.log('types.LOGIN_ERROR...');
        return{
          ...state,
        	isLoggedIn: false,
          status: null,
        };
        break;
    case types.LOGOUT:

      return {
        ...state,
        isLoggedIn:false,
        status:null,
      }
      break;
    //切莫忘記default返回值
    default:
      return state;
  }
}
reducer其實就是根據一系列action的處理函式,好比我們在前面action中返回的有LOGIN,LOGIN_ING,LOGIN_ERROR等狀態,然後呼叫reducer根據不同的type返回當前最新的state,然後再render ui。

/*************************************connect*************************************/

redux的三部分至此就操作完畢,但如果進行連結起來呢,這裡就用到connect元件,connect是將某一個元件(這裡一般指一個頁面)和store連結起來,目的就是獲取當前頁面所需的state以及dispatch方法。從全域性state中獲取這個頁面需要的資料然後以props的形式傳遞給當前頁面。)

import React, { Component } from 'react';
import {
  StyleSheet,
  TextInput,
  Text,
  View,
  TouchableHighlight,
  ActivityIndicator,
} from 'react-native';

import {connect} from 'react-redux';//將我們的頁面和action連結起來
import {bindActionCreators} from 'redux';//將要繫結的actions和dispatch繫結到一起
import * as actionCreators from '../actions/loginActions';//匯入需要繫結的actions
import Modal from 'react-native-modalbox';
import Home from './home';


/**
登陸頁面
**/
class Login extends Component{

  constructor(props){
    super(props);

    this.state={
    }

    this.login=this.login.bind(this);
    this.onChangePhone=this.onChangePhone.bind(this);
    this.onChangePswd=this.onChangePswd.bind(this);
  }

   onChangePhone(text){
     this.setState({'phone':text,});
   }

   onChangePswd(text){
     this.setState({'password':text,});
   }

   login(){

     if(!this.state.phone||!this.state.password){
       alert('使用者名稱或密碼不能為空!');
     }else{
       this.refs.modal.open();//loading 狀態
       this.props.actions.login({'phone':this.state.phone,'password':this.state.password});//dispath 登陸
     }
   }

   //該方法首次不會執行,如果返回false,則reduer不會執行,,
   shouldComponentUpdate(nextProps,nextState){
     const {isLoggedIn,navigator}=nextProps;
      if(isLoggedIn){
        this.setState({phone:'',password:''});

        navigator.push({
          component:Home,
          name:'Home',
        });
      }
     return true;
   }

   render(){
    console.log('render...');
     return(
      <View style={{flex:1}}>
      <View style={{padding:20,marginTop:50}}>
      <View style={styles.item}><Text style={{width:70}}>手機號碼</Text>
      <TextInput
      style={styles.input}
      onChangeText={this.onChangePhone}
      placeholder='請輸入手機號碼'
      value={this.state.phone}
      />
      </View>
      <View style={styles.item}>
      <Text style={{width:70}}>密碼</Text>
      <TextInput
      style={styles.input}
      onChangeText={this.onChangePswd}
      placeholder='請輸入密碼'
      password={true}
      value={this.state.password}
      />
      </View>

      <TouchableHighlight style={styles.button}
       underlayColor='#000000' onPress={this.login}>
      <Text style={{fontSize:16,color:'#fff'}}>登陸</Text>
      </TouchableHighlight>
      </View>

      <Modal
      style={styles.modal}
      ref='modal'
      isOpen={this.props.status=='doing'?true:false}
      animationDuration={0}
      position={"center"}
      >
      <ActivityIndicator
      size='large'
      />
      <Text style={{marginTop:15,fontSize:16,color:'#444444'}}>登陸中...</Text>
      </Modal>
      </View>
     );
   }
}

const styles =StyleSheet.create({
    item:{
      flex:1,
      flexDirection:'row',
      alignItems:'center',
      height:50,
      borderBottomColor:'#ddd',
      borderBottomWidth:1,
    },
    input:{
      flex:1,
      fontSize:14,
    },
    button:{
      backgroundColor:'#1a191f',
      height:50,
      marginTop:40,
      justifyContent:'center',
      alignItems:'center'
    },
    modal: {
      justifyContent: 'center',
      alignItems: 'center',
      width:150,
      height:150,
      borderRadius:10,
    },
});

//根據全域性state返回當前頁面所需要的資訊,(注意以props的形式傳遞給Login)
function mapStateToProps(state){
  return{
    isLoggedIn:state.user.isLoggedIn,
    status:state.user.status,
  };
}
//返回可以操作store.state的actions,(其實就是我們可以通過actions來呼叫我們繫結好的一系列方法)
function mapDispatchToProps(dispatch){
  return {
      actions: bindActionCreators(actionCreators, dispatch)
  };
}

//連結起來
export default connect(mapStateToProps,mapDispatchToProps)(Login);

上面的程式碼不用仔細看,主要是尾部的部分,

mapStateToProps方法:根據全域性state返回當前頁面所需的資料然後以props的形式傳遞給當前頁面(Login)。

mapDispatchToProps:該方法就是將dispatch和當前頁面引入的actionCreators繫結在一起,然後就可以輕鬆呼叫。

如:login方法中的:

this.props.actions.login({'phone':this.state.phone,'password':this.state.password});//dispath 登陸

這樣整體整合就完畢了,這裡簡單總結下:

1.首先我們建立全域性的store(基於所有的reducer)在APP最外層引用,然後我們建立action(可以根據頁面或者某種類別來定義)。接著我們建立reducer(可以設計成跟action一一對應)。最後通過connect將它們和頁面連結起來,至於action和reducer的內容,可以等頁面編輯OK後再進行設計。

2.執行簡單流程:在頁面中首先呼叫對應action方法(傳遞引數)--->執行相應的業務邏輯,然後呼叫dispatch(action)(將結果以action的形式傳遞給reducer)--->在reducer中根據type欄位然後返回最新的state,然後在進行render具體的ui。

相關推薦

React Native整合Redux框架講解應用

          學過React Native的都知道,RN的UI是根據相應元件的state進行render的,而頁面又是由大大小小的元件構成,導致每個元件都必須維護自身的一套狀態,因此當頁面複雜化的時候,管理state會相當吃力的。而redux提供了一套機制來組織管理整

React Native之ListView的講解應用

          在安卓原生開發中,ListView是很常用的一個列表控制元件,那麼React Native(RN)如何實現該功能呢,這裡簡單的講解下。        ListView.js原始碼截圖:               從原始碼中可知RN中的ListView是

React Native整合Redux

學了一段時間React-Native,開始學習別人的專案,發現用到了Redux,幾經搜尋,大多都是講Redux框架的歷史,起源,如何牛逼,分析架構,舉栗子,怎麼用,卻沒有說怎麼配置,下面這篇文章講解的

React Native之ViewPagerAndroid講解應用

   做過移動開發的朋友都知道,ViewPager控制元件在應用場景是在常見不過了,React Native(RN)給我們提供了一套針對安卓平臺的component:ViewPagerAndroid。不過github上面有人實現了跨平臺的ViewPager,只是體驗上有點欠

一次掌握 React React Native 兩個框架

此係列文章將整合我的 React 視訊教程與 React Native 書籍中的精華部分,給大家介紹 React 與 React Native 結合學習的方法。 1. 軟體開發語言與框架的學習本質 我們在開始系列文章的技術點內容前,花一點時間探討一下軟體開發語言以及框架的學習本質,相對於整個技術點的講解,花這

React Native學習筆記之--向原生應用整合RN頁面

React Native學習筆記之–向原生應用中整合RN頁面 根據在官方文件的學習要向已有的原生專案中新增RN元件最重要的就是以下幾步: 1.Understand what React Native components you want to in

React Native Android 原始碼框架淺析(主流程及 Java JS 雙邊通訊)

1 背景 有了前面《React Native Android 從學車到補胎和成功發車經歷》和《React Native Android Gradle 編譯流程淺析》兩篇文章的學習我們 React Native 已經能夠基本接入處理一些事情了,那接下來的

React Native中的DeviceEventEmitter.addListenerDeviceEventEmitter.emit

ice navigator 訂閱 shu reac 如何 沒有 解釋 http   官方文檔沒有對這兩個方法做很好的解釋,需要自己找資料研究。看了幾篇文章,總結是和訂閱發布模式差不多,用來事件監聽發送的。 React Native學習之DeviceEventEmitter傳

React Native使用Redux總結

war lda 技術 pan strong blog connect lar win 1>npm安裝redux: "react-redux": "^5.0.5", "redux": "^3.7.1", "redux-thunk": "^2.2.0" 2>大

shell 指令碼的講解 應用

shell指令碼程式設計 作用:通過命令列解析的方式,自動執行設定好的程式或命令程式碼。(若將指令碼掛到定時任務中,就會自動在非工作時間裡自動觸發執行程式)   Shell指令碼檔案以“.sh”結尾 規範的Shell指令碼第一行會指出由哪個程式(直譯器)來執行指令碼中的內容。在linux b

每日知識總結計劃(java、android、react native、web框架、js、css、html、ajax)首頁

作為一名資訊系的學生,現在學的太多,忘得也快,但是實在不忍心辛苦理解的知識就這樣慢慢被自己忘記。 所有這篇帖子作為今天起(2018.10.16  17:32),記錄每天得知識總結首頁。 下面得帖子連結分為一個月為一個單位做記錄,每天的記錄就在當月的一個月的帖子上更新。 20

React Native整合Touch ID和Face ID

前言: 使用Touch ID也稱為指紋身份驗證在移動應用程式中非常流行。Touch ID功能可保護應用程式並使其成為使用者的無縫身份驗證流程。 許多銀行應用程式,如美國銀行,發現,大通,使用Touch ID身份驗證,實現安全和無縫的身份驗證。 使用者無需在每次登入時鍵入長密碼,只

【新書推薦】【2018.05】有源整合天線的設計應用

【2018.05】有源整合天線的設計與應用Design and Applications of Active Integrated Antennas,共276頁。 如果需要電子版,請聯絡QQ:3042075372。 本書指導專業人士在設計用於各種標準的無線通訊裝置的有源整合天線

Javascript 設計模式系統講解應用已完結

第1章 課程介紹 學習設計模式的必要性,課程包含的知識點,課程安排,學習前提 1-1 導學 第2章 面向物件 講解javascript中的面向物件的概念,包括 ES6 class 語法、UML 類圖、以及面向物件三要素 2-1 搭建開發環境1 2-2 搭建開發環境2 2-

Javascript 設計模式系統講解應用(完整版)

第1章 課程介紹 學習設計模式的必要性,課程包含的知識點,課程安排,學習前提 1-1 導學 第2章 面向物件 講解javascript中的面向物件的概念,包括 ES6 class 語法、UML 類圖、以及面向物件三要素 2-1 搭建開發環境1 2-2 搭建開發環境2 2-

和我一起入坑-React-Native-加入Redux的TodoList

讀前須知 這個專案是第一次使用Redux的例項,並不具有專業性的理論知識。純粹分享一次開發過程與心得。之前寫了一篇沒有加入Redux的React Native ToDoList的小博文。這個專案也是在原來的基礎上進行裝修完成的。目的是為了體驗一下高深莫測的Redux

react-native整合到現有原生專案

必須具備react-native的開發環境 建立結構目錄 建立一個名為rn_test的資料夾(這個資料夾是存放react-native專案的),在rn_test資料夾中建立名為android的資料夾(是存放android專案的)把原生專案複製進去,這裡我建立了一個新的 引入rea

Javascript 設計模式系統講解應用(雲盤下載)分享

第1章 課程介紹 學習設計模式的必要性,課程包含的知識點,課程安排,學習前提 1-1 導學 第2章 面向物件 講解javascript中的面向物件的概念,包括 ES6 class 語法、UML 類圖、以及面向物件三要素 2-1 搭建開發環境1 2-2 搭建開發環境2

React Native整合Sentry之附加配置

這些是您可以在javascript程式碼中呼叫的函式: import { Sentry, SentrySeverity, SentryLog } from 'react-native-sentry'; // disable stacktrace merging

React Native整合Sentry之CodePush

如果您想與CodePush一起使用哨兵,您必須向我們傳送CodePush版本: import codePush from "react-native-code-push"; codePush.getUpdateMetadata().then((update) =>