淺入react-native使用redux_Redux

來源:互聯網
上載者:User

Redux 是 JavaScript 狀態容器,提供可預測化的狀態管理。

初學這個,覺得網上有些文章並不那麼容易看懂,這裡用淺白的話簡單介紹一下Redux在react-native的使用。

說白了就三個主要東西,Action,Store以及Reducer。


Action:主要用來觸發一些事務改變state,平時都用setState改變狀態。
Reducer:在觸發上面的Action後,對Action進行處理,並返回一個新的state。

Store:每個程式有且只有一個Store,作為一個根節點管理state,很多個state等於子節點。Action和Reduce就是通過Store才能聯絡到一起。


直接來個案例,順便對比一下用傳統的setState方法和使用Redux來控制state的區別

先來搭配一下Redux環境

npm install --save redux 【redux的包】

npm install --save react-redux  【react-redux是redux需要依賴的包】

npm install --save redux-thunk   【redux-thunk是用來讓redux有非同步action事務】


先看工程的目錄結構,有三個檔案夾,就是上述三個東西。。。。。


Store留在最後才說,因為這是其他兩個串連的對象。


這三個東西的流程是這樣的,

1.Store不用多說,都是拷貝一份代碼完事。然後把store的綁在根頁面的屬性內。

2.Reducer,先建一個索引的檔案作為綁定Reducer的(也是拷貝的功夫),然後就可以寫多個Reducer了。Reducer是通過Action分發過來的action,找到合適類型的Reducer,Reducer的邏輯代碼就會產生新的一個state,最後return給Store。

3.Action,給頁面觸發用的,當頁面綁定好connect,就可以通過props擷取【dispatch分發器】和【Store管理的state】,dispatch分發器在頁面使用:(1)事件會傳到Action。(2)Action裡再用dispatch分發到Reducer。(3)Reducer已經綁定了Store,只要return一個state給Store,Store就會把新的state替換舊的。

4.從以上三步可以看出,這三個東西的運作流程,但會有點模糊,我看很多貼的時候都會有這個疑問,我現在很熟悉redux的原理了,我到底怎麼統一管理state呢。回顧一下這裡第1點,Store是要綁在根頁面的,因此我們可以獲得Store管理的state。再回顧一下第2點,Reducer需要一個索引綁定多個Reducer的,因此每個Reducer返回的新的state是都得經過綁定這個索引的。最後回顧第3點,頁面獲得Store管理的state。綜合以上分析,根據Reducer的索引可以找到對應的state,然後讓頁面獲得對應的state。

Redux其實說白了,比直接用傳統的state是要麻煩很多,因為寫多了很多代碼才能達到使用傳統的state的效果。但是維護這個很關鍵,統一管理state,在維護上,絕對比傳統的state要快,因為有商務邏輯代碼改動的話,不要再開啟那臃腫的介面慢慢找,在Redux架構可以快速找到相應代碼,而且看到的代碼是簡潔的。這大概是前期費那麼大勁也要使用Redux的原因吧。


先來Action,

LoginAction.js是一個處理登入的action,這裡寫得很簡單,看看帳號密碼對不對。

import * as types from './ActionType';export function performLoginAction(username, password) {return (dispatch) => {console.log("run......performLoginAction.....performLogin");dispatch(performLogin());if (username === 'ljy' && password === '123') {dispatch(receiveLoginResult("succeed"));} else {// dispatch(receiveLoginResult("fail"));dispatch(receiveLoginResult("fail"));}}}function performLogin() {return {type: types.PERFORM_LOGIN_ACTION,}}function receiveLoginResult(result) {return {type: types.RECEIVE_LOGIN_ACTION,data: result}}

上面匯入的ActionType.js是下面這段你沒看錯,這個檔案主要是用來寫一些Action類型,為什麼需要這個呢。因為我們平時管理RN的資料,都是用state管理的,這個redux作為一個中介軟體統一管理所有state,所以有個Action類型,讓Action能正確地分發給下一級Reducer。

export const PERFORM_LOGIN_ACTION = 'PERFORM_LOGIN_ACTION';export const RECEIVE_LOGIN_ACTION = 'RECEIVE_LOGIN_ACTION';

先不說函數調用的問題,先要理解每個函數的作用,後面用到的時候會提到。

performLoginAction(username, password)這個方法是用來處理登入的,裡面return一個方法,可以看到方法裡面有多個dispatch方法。dispatch是用來傳遞給下一級的。action的下一級是Reducer,可見performLoginAction(username, password)方法下面有兩個方法,都是返回一個對象的,那就是把對象傳過去給Reducer。那最大的疑問是(dispatch)=>{}括弧裡的dispatch從哪裡傳過來的,上面流程第3點,頁面綁定資料connect就能擷取dispatch,那這裡Action的dispatch當然是從頁面傳過來的啦。


再來Reducer,

需要一個索引,建一個index.js,代碼就是拷貝,要改的是combineReducers裡面的對象,比如login是索引(key),對象就是引入的LoginReducers。

import {combineReducers} from 'redux';import LoginReducers from './LoginReducers';import LoginReducers2 from './LoginReducers2';const rootReducer = combineReducers({login: LoginReducers,login2: LoginReducers2});export default rootReducer;
從索引可以看到有兩個Reducer,這裡給出其中一個LoginReducers.js,另一個大同小異。

import * as types from '../action/ActionType';const initialState = {loading: false,data: '',}export default function login(state = initialState, action) {switch (action.type) {case types.PERFORM_LOGIN_ACTION:return {...state,loading: true,};case types.RECEIVE_LOGIN_ACTION:return {...state,loading: false,data: action.data};default:return state;}}

Action裡的dispatch傳到Reducer來了,在上面Action的dispatch只有一個參數,這個參數傳到這個Reducer的提供了的login方法的action參數,因為第一個參數是內建的state參數,這裡login方法有個switch,根據Action類型返回對應的state,否則返回原來的state。

這段是靠js功底,應該能看懂吧?...state是一個文法,意思是把state裡所有的索引值對列出來,比如說:loading:false,data:"",


再來Store,

configure-store.js,大部分是拷貝的,這個可能跟傳統的redux寫法有些不一樣,因為用了redux-thunk,這個的作用上面有說到啦。

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;}

上面講到Reducer的索引檔案,在這裡用上了,關聯到Store了。匯入的rootReducer就是我們上面寫得索引。 


成功了一大半了,理解了Redux方面的原理,結合上述代碼,Redux這塊就簡單入門了。還有什麼沒做呢。寫好Redux部分,就差在頁面上調用了。


最後到Page,

頁面根目錄Root.js,用react-redux的Provider綁定Store。依舊是拷貝,作用是匯入Store綁定到介面。

import React, {Component} from 'react';import{} from 'react-native';import {Provider} from 'react-redux'import configureStore from './store/configure-store'import App from './App'const store = configureStore();export default class RootApp extends Component {render() {return (<Provider store={store}><App /></Provider >)}}

根目錄綁定好Store後就可以在子頁面使用了。這裡子頁面的Component匯出的話,需要用react-redux提供的connect匯出。下面詳細解釋綁定資料到子頁面。

為了更好對比setState和dispatch兩種方式改變state,以下TextInput控制項的代碼用到了setState,TouchableOpacity控制項的代碼用到了dispatch。


Provider包含的根頁面,App.js

import React, {Component} from 'react';import {AppRegistry,StyleSheet,Text,View,TouchableOpacity,TextInput} from 'react-native'import {connect} from 'react-redux';import {performLoginAction} from './action/LoginAction';class App extends Component {constructor(props) {super(props);this.state = {username: '',psw: ''};}render() {const {dispatch, login} = this.props;return (<View style={{flex: 1, justifyContent: 'center'}}><View style={{height: 100, margin: 10}}><View style={{flex: 1}}><TextInputstyle={{fontSize: 20}}underlineColorAndroid={'transparent'}placeholder={"帳號"}onChangeText={(username) => this.setState({username})}value={this.state.username}/></View><View style={{height: 1, backgroundColor: '#eee'}}/><View style={{flex: 1}}><TextInputstyle={{fontSize: 20}}underlineColorAndroid={'transparent'}placeholder={"密碼"}onChangeText={(psw) => this.setState({psw})}value={this.state.psw}/></View><View style={{height: 1, backgroundColor: '#eee'}}/></View><View style={{margin: 10, alignItems: 'center'}}><TouchableOpacity onPress={()=> {dispatch(performLoginAction(this.state.username, this.state.psw));}}><Text style={{fontSize: 30}}>登入</Text></TouchableOpacity></View><View style={{height: 100, margin: 10, justifyContent: 'center', alignItems: 'center'}}><Text style={{height: 30, fontSize: 20, margin: 10}}>{login.data}</Text></View></View>);}}function mapStateToProps(state) {const {login} = state;return {login}}export default connect(mapStateToProps)(App);


 

最後一行的connect是在子頁面或者說控制項吧,進行綁定資料到Store。connect需要mapStateToProps方法返回的一個Reducer,mapStateToProps方法有個參數state,這個是Store統一管理的state,也就是根節點。上面有一個Reducer的索引是login,學了js的這句應該看得懂的,const {login} = state;等於const  login = state.login;

有點感覺吧。。。。。。Reducer的索引就是這樣用的,把每個state區分開來,但是Store又是一個根節點,把所有用索引區分開來的state統一在一個根節點上。

function mapStateToProps(state) {const {login} = state;return {login}}export default connect(mapStateToProps)(App);


有了connect這一步,

這個頁面或者說控制項,props屬性裡就有東西拿了。可以擷取dispatch,這個分發器太熟悉了,上面講到爛了。。。。。還有一個login,這個login哪裡來的。就是mapStateToProps方法返回的索引為login的Reducer,Reducer是返回state的,所以有這個參數login,本質上是一個state。這裡頁面的state就是login,login是唯讀不能寫的,不能用setState去改變它,要用dispatch分發事件(並非state)給Action,Action分發(並非state)給Reducer,Reducer返回state給Store,Store再用新的state替換對應索引的state。

const {dispatch, login} = this.props;

拿到state,是唯讀,直接用就好了,把平時setState的習慣改為dispatch寫。redux就入門了。


簡單介紹了一下React-Native使用了一下Redux。相關源碼百度搜,很多。。。。。。







相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.