1. 程式人生 > >react-native 之 state 和 props 以及 redux 和 react-redux

react-native 之 state 和 props 以及 redux 和 react-redux

Component 中 state 和 props 的區別;

元件Component中狀態state和屬性props的區別

state props
state是在元件內部定義的一個特殊物件{}
既起到元件內部的一種快取作用,
也具備由於state變化而激發生命週期中渲染的方法
render()被回撥的作用。且使用域僅限於元件內部。
props是元件屬性,連線了外部父元件和元件內部的使用域。
它的改變激發宣告週期方法componentWillReceiveProps(nextProps)
和渲染的方法render()逐次被回撥。連線外部父元件,
可以通過父元件向其傳遞value、function
等,連線內部元件,
this.props快取了當前元件的所有props屬性內容
{value, function}=this.props;

程式碼解釋 props

 /**
   * 通過封裝 FlatList 自定義一個列表元件
   */
export default class MyFlatList extends Component {
    constructor(props) {
        super(props);

    }

   ...
    /**
     *象元件FlatList中的
     *ref、ListHeaderComponent、ItemSeparatorComponent、
     *data、keyExtractor、onRefresh、refreshing等都是props屬性;
     *
     * 象這種樣式的定義 this.props.itemSeparator、
     * this.props.onRefresh、this.props.refreshing、this.props.onLoadMore等
     * 屬於自定義元件MyFlatList的屬性,是我們依照FlatList所定義的。
     * 類似象外部開放的介面一樣,就像這裡FlatList使用自己的
     * 屬性ListHeaderComponent、ItemSeparatorComponent、data等一樣來使用;
     * @returns
{XML} */
render() { return (<View style={{flex: 1, backgroundColor: Colors.bg}}> <FlatList ref={(flatlist) => this.flatlist = flatlist} ListHeaderComponent={this._header} renderItem={this._renderItem} ItemSeparatorComponent={this
.props.itemSeparator} data={this.props.data} keyExtractor={this._keyExtractor} onRefresh={this.props.onRefresh} refreshing={this.props.refreshing} onEndReachedThreshold={0.1} onEndReached={this.props.onLoadMore} initialNumToRender={3} getItemLayout={(data, index) => ({ length: 250, offset: (250 + 10) * index, index })} /> </View>); } }

這是使用MyFlatList,來看下它的這個props

export default class FlatlistScreen extends Component {
 ...
    /**
     *這裡MyFlatList的 itemSeparator、data、onRefresh 、refreshing 、onLoadMore 
     *就是FlatList中使用this.props.xxx來定義的。 
     * @returns {XML}
     */
    render() {
        return (<View style={styles.container}>
           ...
            <MyFlatList
                {...this.props}
                itemSeparator={() => this.separator()}
                data={this.state.dataSource}
                onRefresh = {()=>this.onRefresh()}
                refreshing = {this.state.isRefresh}
                onLoadMore = {()=>this.onLoadMore()}
            />
        </View>);
    }
}

除了以上,如果是對資料內容的props屬性的變化,如上面程式碼的data變化,必然會激發MyFlatList元件生命週期方法componentWillReciveProps回撥,這裡我們可以在render方法回撥前,對資料再次進行判斷處理。
**這就是props屬性功能和作用!!**

程式碼解釋 state

export default class FlatlistScreen extends Component {
    constructor(props) {
        super(props);
        this.unmount = false;
        this.state = ({
            dataSource : [],
            isRefresh: true,
        });
    }
    ...
    /**
     * 功能:使用箭頭函式,不使用bind;因為bind函式每呼叫一次就會建立一個新的函式
     */
    onRefresh() {
        this.setState({
            isRefresh: true,
        });

        //功能:製造重新整理效果
        this.interval = setInterval(() => {
            clearInterval(this.interval);
            //功能:製造上拉載入更多的效果
            const data = [];
            for (let i = 0; i < 8; i++) {
                data.push({id: i, title: '親子旅遊日帶娃兒玩' + i + '折起', state: '已過期', date: '2018/06/0' + (i - 8)},)
            }
            this.setState({
                dataSource: data,
                isRefresh: false,
            });

        }, 2000)
    }

   ...

    render() {
        return (<View style={styles.container}>
           ...
            <MyFlatList
                {...this.props}
                itemSeparator={() => this.separator()}
                data={this.state.dataSource}
                onRefresh = {()=>this.onRefresh()}
                refreshing = {this.state.isRefresh}
                onLoadMore = {()=>this.onLoadMore()}
            />
        </View>);
    }
}

看構造方法這裡

this.state = ({
            dataSource : [],
            isRefresh: true,
        });

這就是state的定義方式。通過改變dataSourceisRefresh的值就能激發render再次渲染元件。
比如這裡的onRefresh方法使用了

 this.setState({
      dataSource: data,
      isRefresh: false,
 });

來控制改變state的時機,來控制組件渲染的時機。
**這就是狀態state的使用!!**

react-native 與 Redux 的配合使用;

Redux使用中,一些必知的概念

Redux state action reducers
Redux 是 JavaScript 狀態容器,
提供可預測化的狀態管理。
使用 Redux 的一個益處,
就是它讓 state 的變化過程變的可預知和透明。
以一個物件樹的形式儲存在於一個單一的 store 中,
惟一改變 state 的辦法是觸發 action。
一個描述發生什麼的指示器物件。
action 內必須使用一個字串型別的 type 欄位,
來表示將要執行的動作。
且應該儘量減少在 action 中傳遞的資料;
描述 action 如何改變 state 樹。
reducer 就是一個純函式,接收舊的 state 和 action,返回新的 state。

這裡是我基於Redux實現的已給簡單操作流程原始碼
結合原始碼+圖例,分析下redux的執行操作流程,解讀redux是怎樣原理!

登入操作執行圖

現在定位在登入頁面,處於未登入狀態,需要點選登入操作。
這裡寫圖片描述

圖並結合原始碼分析

登入頁面的部分原始碼,展示了登入頁面的UI
這裡寫圖片描述
從原始碼中50行看到,點選登入按鈕,則呼叫方法login() ,而login()這個方法是從this.props中解構賦值拿出來的,就是原始碼37行所示。
疑問1? this.props中的login()是從哪裡來的,怎麼會在this.props中?!
接著看同一js檔案中的程式碼片段
這裡寫圖片描述
這裡有一個方法非常的重要connect(),她是幹什麼的,這裡可以解答。
簡單的說是,就我們所看到的程式碼從64到74行,connect()裡面有兩個回撥函式,第一個回撥的是state(Login頁面的state),第二回調的是dispatch(Login頁面用來進行分發登入操作的Action)。通過connect()()實現了 回撥函式中 status、isSuc、user 和 login() 他們與當前的元件(登入頁面)的this.props繫結,也就是他們被注入到了this.props中。
所以,點選登入的執行流程是這樣的:
點選登入按鈕——>呼叫this.props中的login方法——>派發登入操作的action ——>.. reducer處理…導致store的state樹中登入元件的state發生變化 … ——>原始碼中65行執行回撥,同時UI將會執行重新的重新整理、渲染——>渲染過程中需要的內容,從回撥中的state中獲取、賦值。

繼續深入…
登入功能的Action中有兩類內容,一是需要傳遞的使用者資料物件
這裡寫圖片描述
二是派發的Action構建函式
這裡寫圖片描述
圖中可以清晰看到,Action有兩種實現方式,其中最後一種是非同步的Action構建函式,前面則是同步的Action構建函式;通常非同步的Action中會呼叫同步的Action。而同步的Action有一個特點就是有一個約定成俗的欄位叫type,標識著Action的通知型別。
當執行登入操作,使用redux進行登入操作的action進行派發的時候,呼叫了非同步的Action,非同步的通知由在內部執行非同步操作,呼叫同步的action。執行到這裡,action就會被分發到哪裡呢??reducer
reducer也分為兩部分,一是登入頁面內容展示登入元件的state
這裡寫圖片描述
是一個登入操作在執行到reducer時的處理,進行復制、賦值、填充的state模型的資料物件,store樹中的一個物件。
reducer的處理也很簡單,就是根據action的指定處理方式type,進行處理。處理完成之後,返回一個新的state物件。看原始碼是不是這樣的?!
這裡寫圖片描述

執行處理到這裡,想到你已經發起疑問了。疑問2?總覺得,到reducer處理之後與元件容器那兒回撥,直到頁面再次渲染,沒有什麼關聯??!它們到底是怎麼建立關係的呢?
當然是通過Redux,以及處理非同步action需要用到的中介軟體(標準的做法是使用 Redux Thunk 中介軟體)。
看這裡,首先是集合管理action的處理,對reducer的管理
這裡寫圖片描述
然後把對reduer的管理,以及處理結果再交給redux
這裡寫圖片描述
並且也同時,把上面的兩個reduer對應的處理結果state,作為store樹的分支,繫結到了store中,進行統一管理和處理。而且還有一點很關鍵、很重要!也是急需解決的重要疑問——store樹長什麼樣子?? 經過我的實踐和測試對比得出結論, store樹 中的登入元件的state,其資料內容的樣子是和上圖中原始碼第10行 rootReduer 中的資料結構LoginIn是對應的。也就是說他們是互相對映的。即, store與rootReduer 在資料結構上是一致的, store樹 就是通過這樣的rootReduer 中一條條 {key:value} 資料拼湊到一起所組成的物件。如果有點疑問,自己可以動手試一試,並用下圖再加深下印象
這裡寫圖片描述
store樹是用來管理元件state資料的,好,因為我們使用了全域性提供store的方式進行了處理,這裡寫圖片描述
store中的屬性,我們可以在專案中進行全域性使用。
所以,在connect()()程式碼塊中,當state發生變化,產生回撥,我們可以通過state.LoginIn.status、state.LoginIn.isSuc、state.LoginIn.user來指定拿到當前元件對應的state資料。而state.LoginIn的呼叫方式就是從store樹中取出LoginIn對應的state,而LoginIn是哪來的?也許內容有點多,蒙圈了,其實就在原先這裡第11行程式碼。
這裡寫圖片描述
所以,我之前總結的結論,store樹中的登入元件的state,其資料內容的樣子是和上圖中原始碼第10行rootReduer中的資料結構LoginIn是對應的。也就是說他們是互相對映的。 store與rootReduer 在資料結構上是一致的, store樹 就是通過這樣的rootReduer 中一條條 {key:value} 資料拼湊到一起所組成的物件。是正確的!到這裡則回答了上面的疑問2?,同時也解決了Redux的使用以及執行原理。

相關推薦

react-native state props 以及 redux react-redux

Component 中 state 和 props 的區別; 元件Component中狀態state和屬性props的區別 state props state是在元件內部定義的一個特殊物件{},既起到元件內部的一種快取作用,也具備由於

React NativeText控制元件屬性樣式

屬性 numberOfLines 文字行數限制,新增後超過限制行數文字會在末尾預設以…的形式省略。 ellipsizeMode 設定文字縮略格式,配合numberOfLines使用,values: * tail:在末尾…省略(預設值) * c

React NativeAndroid iOS在點選觸發事件時的相容性處理

最近,我在專案中遇到了一個bug,bug的情況描述大致如下: 當點選按鈕A時,彈出彈層,彈層有一個按鈕B,邏輯是:當點選按鈕B時,首先彈層消失,緊接著開始調取C介面流程。在Android上正確顯示,但是iOS中只是彈層消失,並沒有調取C介面事件。 對於這種情況,我之前開發過

react native原生RN的互動

前言:前端時間隨著自己的學習和研究,也寫了幾篇關於react native的文章,雖然都是比較簡的,但是都是根據自己的效果來做的流程,所以還是比較實用的,可以避免很多的坑。這篇react native

React NativeRedux動態插入reducer

       RN的使用狀態管理我們使用的方式大多數有倆種,分別是redux和mobx這倆種狀態工具。那麼這次選取redux考慮一個東西---reducer的動態注入。     首先說一下背景----假如說你的app有100 reducer,而我們的store是唯一的。那麼我

React native android的圖示啟動圖片

哎哎呀呀,上篇說到了react native的IOS的圖示和啟動圖片的設定,其實最主要的是尺寸!相應的尺寸設定好了以後就不會報錯了!ok~這篇說的是React native的android的圖示和啟動頁面!!!!!1.圖示:其實android的圖示設定很簡單,一般情況下只需要替換就可以了(當然你也可以不去替換

React Native內部方法常用幾種寫法呼叫規則

1 簡單部分程式碼 export default class App extends Component<Props> { render() { return (

React-NativeXcode虛擬機器快捷鍵重新整理彈出選單不能用

1:描述  有時候執行在Xcode虛擬機器上的react-native專案  command+T和command+D沒有效果 2:原因 其實這個問題主要是由於iOS Simulator和鍵盤之間斷開了連線導致的, 也就是說iOS Simulator不在接受鍵盤的事件

React NativeRedux使用詳解Reducers(30)

React Native之Redux使用詳解之Reducers 一. Reducers Actions 描述發生了什麼,但不能指定響應中state怎麼變化,這是Reducers的工作。 1. 設計State Shape 在Redux中,所有sta

React Native學習ListView的單選以及記錄資料

var mSelectWhat = -1; var ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 }); //當且僅當cell中的任意兩行不相等時才重新渲染\ export default class Desig

React Native - 3 View, Text簡介以及onPress & onLongPress事件

分享 關鍵字 添加 res com ive img src 解釋 我們要生成如下的構圖 直接上圖,不解釋。 如下圖所示,定義函數,函數之間不需要逗號,在元素上添加事件,使用關鍵字this.{function name}

React NativeTouchable四組件

width font clas 容易 原生 ber 支持 cit out 一、TouchableHighlight 概念: 本組件用於封裝視圖,使其可以正確響應觸摸操作。當按下的時候,封裝的視圖的不透明度會降低,同時會有一個底層的顏色透過而被用戶看到,使得視圖變暗或變亮。

React Native登錄界面的布局

處理器 圖片 blank 轉載 圓角 print extends cit hit 版權聲明:本文為博主原創文章,未經博主允許不得轉載。 代碼註釋比較詳細 /** * Sample React Native App * https://github.com/fa

react native中的聊天氣泡以及timer封裝成的發送驗證碼倒計時

日常 per pad direct 總結 mage str parent erb 今天看來情書寫的文章,研究了一下大佬寫的文章,自己做一點總結。 其實,今天我想把我近期遇到的坑都總結一下:1.goBack的跨頁面跳轉,又兩種方法,一可以像兔哥那樣修改navigatio

react-native遠程圖片修改後APP不更新

reactnative react-native react native 刷新圖片 base64今天在做客戶的項目時,有一個需求是App上要顯示遠端的圖片,而遠端的圖片有可能會更新,但圖片名不變。在react-native中,顯示圖片是用的自帶的Image組件,大家都知道react在更新組件之前都會判斷pr

ES值類型以及

以及 span arc nic ont 一個 永遠 cti 方式 ES的數據類型: 原始類型(值存在棧內存中): Number、String Boolean、undefined、null charAt(inde

使用WebStorm開發React-native基礎

ttr regexp 渲染 hang reg 路徑 tostring png text 配置問題: (1)找不到SDK路徑,或者沒有SDK對應的版本:SDK必須是android-23才可以(更新SDK) 解決方法:環境變量,必須設置Android_HOME

React Nativestate使用詳解

red 什麽 style data return javascrip ets pre fault 什麽是State props是不可改變,只讀的。為了實現交互,就需要用到組件的state。我們將組件看為狀態機,UI是各種各樣的狀態,並在各種各樣的狀態之間可以切換,只需要改

react-native模擬器調試

adb div connect oid native 令行 input 模擬 key 手動觸發搖一搖:adb shell input keyevent 82(有時模擬器搖一搖無效) android studio檢測不到模擬器: 命令行cd到模擬器安裝目錄,找到adb.exe

React Nativethis詳解

過程 show super try this registry alert item rop this引起的錯誤詳解 我們在學習React Native的過程中,肯定經常遇見過undefined is not an object這樣的問題吧,尤其是剛開始學習的