React-redux的原理以及簡單使用

RaoMeng發表於2019-02-22

當一個react專案元件層級越來越深,頁面越來越多的時候,資料在各個元件層級和頁面之間傳遞的需求就會比較多,很多變數也需要做成可全域性管理的。在這個時候,redux和react-redux的使用就很有必要了。它們能幫助我們很方便的進行專案全域性性的資料管理。

下面,就寫一下我自己對 reduxReact-redux 的學習以及使用的心得,權當是對學習過程的一種記錄和分享。

一、redux和React-redux的幾個重要概念

1.1 action

Action 是把資料從應用(這裡之所以不叫 view 是因為這些資料有可能是伺服器響應,使用者輸入或其它非 view 的資料 )傳到 store 的有效載荷。它是 store 資料的唯一來源。一般來說你會通過 store.dispatch() 將 action 傳到 store。

1.2 reducer

Reducers 指定了應用狀態的變化如何響應 actions併傳送到 store 的,記住 actions 只是描述了有事情發生了這一事實,並沒有描述應用如何更新 state。

1.3 store

store就是把action和reducer聯絡到一起的物件,store本質上是一個狀態樹,儲存了所有物件的狀態。任何UI元件都可以直接從store訪問特定物件的狀態。 在 Redux 中,所有的資料(比如state)被儲存在一個store容器中 ,在一個應用程式中只能有一個store物件。當一個store接收到一個action,它將把這個action代理給相關的reducer。reducer是一個純函式,它可以檢視之前的狀態,執行一個action並且返回一個新的狀態。

1.4 Provider

Provider 其實就只是一個外層容器,它的作用就是通過配合 connect 來達到跨層級傳遞資料。使用時只需將Provider定義為整個專案最外層的元件,並設定好store。那麼整個專案都可以直接獲取這個store。它的原理其實是通過React中的Context來實現的。它大致的核心程式碼如下:

import React, {Component} from 'react'
import {PropTypes} from 'prop-types'

export default class Provider extends Component {
    getChildContext() {
        return {store: this.props.store}
    }

    constructor() {
        super()

        this.state = {}
    }

    render() {
        return this.props.children
    }
}

Provider.childContextTypes = {
    store: PropTypes.object
}
複製程式碼

1.5 connect

connect 的作用是連線React元件與 Redux store,它包在我們的容器元件的外一層,它接收上面 Provider 提供的 store 裡面的 state 和 dispatch,傳給一個建構函式,返回一個物件,以屬性形式傳給我們的容器元件。

它共有四個引數mapStateToProps, mapDispatchToProps, mergeProps以及options。

mapStateToProps 的作用是將store裡的state(資料來源)繫結到指定元件的props中 mapDispatchToProps 的作用是將store裡的action(運算元據的方法)繫結到指定元件的props中 另外兩個方法一般情況下使用不到,這裡就不做介紹。。

那麼 connect 是怎麼將React元件與 Redux store連線起來的呢?其主要邏輯可以總結成以下程式碼:

import {Component} from "react";
import React from "react";
import {PropTypes} from 'prop-types'

const connect = (mapStateToProps, mapDispatchToProps) => (WrappedComponent => {
    class Connect extends Component {
        constructor() {
            super()

            this.state = {}

        }

        componentWillMount() {
            this.unSubscribe = this.context.store.subscribe(() => {
                this.setState(mapStateToProps(this.context.store.getState()))
            })
        }

        componentWillUnmount() {
            this.unSubscribe()
        }

        render() {
            return <WrappedComponent  {...this.state}
                                      {...mapDispatchToProps(this.context.store.dispatch)}/>
        }
    }

    Connect.contextTypes = {
        store: PropTypes.object
    }
    return Connect
})

export default connect
複製程式碼

二、redux和React-redux的使用

專案中關於redux的資料夾目錄如下

redux.png

拿管理使用者資訊資料的需求來舉例

第一步,編寫操作使用者資訊的action


import {USER_INFO} from "../constants/actionTypes";
import store from '../store/store'

export const switchUser = (data) => {
    console.log("switchUser()",data);
    return () => {
        store.dispatch({
            type: USER_INFO,
            ...data
        })
    }
}
複製程式碼

第二步,編寫改變使用者資訊並返回新state的reducer

import {USER_INFO} from "../constants/actionTypes";

const redUserInfo = (state = {
    userId: 10001,
    userName: '',
    userOpenid: '',
    userPhone: '',
    userRole: 0
}, action) => {
    if (action === undefined) {
        return state
    }

    switch (action.type) {
        case USER_INFO:
            return {
                ...state,
                ...action
            }
        default:
            return state
    }

}
複製程式碼

第三步,完成store的建立

import {createStore} from 'redux'
import reducers from '../reducers/index'

let store = createStore(reducers)

export default store
複製程式碼

第四步,獲取使用者資訊

//配置程式碼,通過connect將元件和store連線起來
let mapStateToProps = (state) => ({
    userInfo: {...state.redUserInfo}
})

let mapDispatchToProps = (dispatch) => ({})

export default connect(mapStateToProps, mapDispatchToProps)(PageClass)

//通過props獲取使用者資訊
this.props.userInfo
複製程式碼

第五步,修改使用者資訊

import {switchUser} from '../../redux/actions/userInfo'

switchUser({
    userId: 10001,
    userName: '',
    userOpenid: '',
    userPhone: '',
    userRole: 2
})();
複製程式碼

至此就完成了redux+React-redux的一個簡單使用流程

相關文章