Redux 使用流程與個人心得(一)

Redux 是React生態(tài)中重要的組成部分。很多人都說,簡單的應(yīng)用可以不用此工具。但是我個人認(rèn)為,中小型應(yīng)用使用的話,可以使文件結(jié)構(gòu)更加規(guī)范,代碼可讀性更強。因為React提出將展示組件與容器組件分離的思想,所以降低了React 與Redux之間的耦合度。

網(wǎng)上廣為流傳的Redux流向圖,可以幫助我們更好地理解并使用。
Redux Flux.png

我個人粗淺的理解是:
Store的角色是整個應(yīng)用的數(shù)據(jù)存儲中心,集中大部分頁面需要的狀態(tài)數(shù)據(jù);
ActionCreators ,view 層與data層的介質(zhì);
Reduce ,接收action并更新Store。
所以流程是 用戶通過界面組件 觸發(fā)ActionCreator,攜帶Store中的舊State與Action 流向Reducer,Reducer返回新的state,并更新界面。

所以也可以按照這個流程思想,來構(gòu)建代碼的結(jié)構(gòu)了。


實現(xiàn)一個很簡單的結(jié)構(gòu).png

上圖實現(xiàn)的就是輸入輸出的東西。輸入框內(nèi)輸入一些內(nèi)容,confirm后,label顯示相應(yīng)內(nèi)容。

最開始
先安裝幾個庫

npm install --save prop-types
npm install --save react-redux
npm install --save redux

1、首先構(gòu)造界面

component/AddName.js

-這是一個純React代碼 ,結(jié)構(gòu)清晰。

//component/AddName.js
import React, { Component } from 'react';
import PropTypes from 'prop-types'

class AddName extends Component {
  //聲明屬性
  static propTypes = {
    lastname:PropTypes.string.isRequired,
    addNameCreater:PropTypes.func.isRequired,
    lastage:PropTypes.number.isRequired,
    addAgeCreater:PropTypes.func.isRequired,
    addNameAsync:PropTypes.func.isRequired
  }
//點擊事件
  handlerFunc = () =>{
    const inputName = this.refs.inputValueTest.value;
    this.props.addNameCreater(inputName);
  }
  handlerAgeFunc = () =>{
    const inputage = this.refs.inputValueAge.value;
    this.props.addAgeCreater(inputage);
  }
  handlerAsyncFunc = () =>{
    const inputName = this.refs.inputValueTest.value;
    this.props.addNameAsync(inputName);
  }
//渲染界面
  render() {
    const {lastname,lastage} = this.props;   
    return (
      <div>
        <header className="App-header">
          <h1 className="App-title">Welcome to React</h1>
        </header>
        <label> {lastname} </label><br/>
        <input ref="inputValueTest" /><br/>
        <button onClick={this.handlerFunc}>confirm</button><br/>

        <label> {lastage} </label><br/>
        <input ref="inputValueAge" />
        <button onClick={this.handlerAgeFunc}>confirm</button><br/>

        <button onClick={this.handlerAsyncFunc}>Async Confirm</button><br/>
      </div>
    );
  }
}

export default AddName;


2、然后,根據(jù)流程圖,我們需要定義一些操作了,也就是ActionCreator.它會傳達(dá)用戶的操作信息以及一些數(shù)據(jù)

先定義一些常量供我們使用,這里就兩種操作,一是添加名字,二是添加年齡,實際都一樣。為了后面實現(xiàn)reducer的合并強行寫了倆。這寫常量一般都定義在actionTpye文件中

Redux/actionType.js

export const ADDNAME = 'ADDNAME'
export const ADDAGE = 'ADDAGE'

接著就是寫ActionCreator ,定義了一些操作類型,告訴store自己是干什么的,需要什么樣的數(shù)據(jù)。

Redux/actions.js

import { ADDNAME,ADDAGE } from "./action-type";

//包含所有的action creator
export const addNameCreater = (name) =>({type:ADDNAME,data:name})
export const addAgeCreater = (age) => ({type:ADDAGE,data:age})
export const addNameAsync = (name) =>{
    return dispatch =>{
        setTimeout(()=>{
            dispatch(addNameCreater(name))
        },2000);
    }
}

3、Reducer 會接收到action的信息。將會進(jìn)行狀態(tài)(數(shù)據(jù))的處理,相當(dāng)于react中的setState()的功能。如果有多個reducer ,可以使用combineReducers方法將其合并,并暴露出去。

Redux/reducer.js

//包含n個reducer函數(shù)的模塊
import {ADDNAME, ADDAGE} from './action-type'
import {combineReducers} from 'redux'
function addName(state='initRedux',action){ //形參默認(rèn)值
    switch(action.type){
        case ADDNAME:
            return action.data
        default:
            return state
    }
}
function addAge(state=0,action){
    switch(action.type){
        case ADDAGE:
            return action.data
        default:
            return state
    }
}

export const finalReducer = combineReducers({
    addName,addAge
})

其中state='initRedux' 、state=0 相當(dāng)于我們在React組件內(nèi)部初始化state.

4、一切操作還是基于Store 的。類似于中央集權(quán)。所以還要把Store建立出來

Redux/store.js

import {createStore,applyMiddleware} from 'redux'
import {finalReducer } from './reducers'
import thunk from 'redux-thunk'
//生成store對象
const store = createStore(finalReducer,applyMiddleware(thunk));//內(nèi)部會第一次調(diào)用reducer函數(shù),得到初始state 

export default store

因為reducer會更新Store中的狀態(tài)(數(shù)據(jù)),所以需要引入reducer ,并創(chuàng)建store.

到此,流程圖到這里就走完了。不過2、3、4都是redux中負(fù)責(zé)接管React 狀態(tài)的功能。1是React負(fù)責(zé)展示的組件。兩者并沒啥關(guān)系。既然有了展示組件,接下來就要有容器組件了。也就是能夠?qū)eact與redux相關(guān)聯(lián)的一個組件。

5、構(gòu)建容器組件

containers/App.js

import React from 'react'
import {connect} from 'react-redux'
import {addNameCreater,addAgeCreater,addNameAsync} from '../redux/actions'
import AddName from '../component/AddName'
export default connect(
    state => ({
        lastname:state.addName,
        lastage:state.addAge
    }),
    {addNameCreater,addAgeCreater,addNameAsync}
)(AddName)

這里用到了react- redux中的connect ??梢詫eact與redux關(guān)聯(lián)起來。AddName就是第一步寫的組件名。state中關(guān)聯(lián)了React中的屬性。這里面涉及到兩個API,到第二章詳細(xì)描述。

6、添加store

src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from 'react-redux'

import App from './containers/App'
import store from './redux/store'

ReactDOM.render((
//使用Provider 組件將APP主組件包裹住,這樣內(nèi)部組件都有Store種提供的屬性。
    <Provider store={store}>
        <App/>
    </Provider>
), document.getElementById('root'));

這樣就OK了。

文件結(jié)構(gòu).png

上圖是主要的文件結(jié)構(gòu),
-redux 集中管理狀態(tài)(數(shù)據(jù))
-component 專注于React 展示組件部分
-containers 集中處理React與redux交互的部分

此外,redux還可以處理一些異步請求。這樣的話??梢宰龅絛ata 和view 的管理分離,增強了工程結(jié)構(gòu)的可讀性與可維護(hù)性。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容