react中使用redux簡易案例講解

爲何我想要使用redux?react

  前段時間初步上手了react,最近在使用react的過程當中發現對於組件之間通訊的需求比較迫切,尤爲是在axios異步請求後端數據的時候,這樣的需求是特別強烈的!舉個例子:ios

 
// 廠家報告到貨
class ReportArrivalGoods extends React.Component{
    constructor(props){
        super(props);
        this.state = {
            columns:tableHead.ReportArrivalGoods,//這裏是初始化的表頭,內容較多,不顯示出來了
            data: []
          };
    }

    componentDidMount(){
     axios(
        {
            method: 'get',
            url: 'http://172.89.1.79/LogisticsSporadicBoardBackEnd/index.asmx/ReportArrivalGoods'
        })
        .then(
            res => {    
         this.setState(
                  data:NewState
            );
            }
        )
        .catch(
            error => {
                console.log(error);
            }
        );
    }

    render(){
        return(
            <Table
            style={{width: '100%'}}
            columns={this.state.columns}
            data={this.state.data}
            border={true}
            maxHeight={tableMaxHeight}
          />
        );
    }
    
}
 
 

  咱們聚焦於下面的componentDidMount()函數web

    componentDidMount(){
     axios(
        {
            method: 'get',
            url: 'http://172.89.1.79/LogisticsSporadicBoardBackEnd/index.asmx/ReportArrivalGoods'
        })
        .then(
            res => {    
         this.setState(
                  data:NewState
            );
            }
        )
        .catch(
            error => {
                console.log(error);
            }
        );
    }

  這是你們都很熟悉的react生命週期鉤子函數,我作了這樣一件事:頁面渲染完向後臺請求數據並顯示到頁面上。可是用過axios的都知道,他跟ajax同樣,都是異步的,也就說,你發處請求後就會當即執行後面的代碼了,等你請求結果回來了纔會執行then()和catch()。一開始我簡單粗暴的直接把整個函數體寫進了鉤子中,實現是沒問題了,但是要使用鉤子函數請求不一樣數據的組件有5個,要是每一個組件都寫這麼一長串代碼,一方面很差看,另外一方面重複代碼太多了。因而我想到了把這段函數體封裝起來,因而就有下面的代碼ajax

 

//webservice數據請求函數
function AxiosGet(desinationURL){
    axios(
        {
            method: 'get',
            url: desinationURL
        })
        .then(
            res => {

                    );
            }
        )
        .catch(
            error => {
                console.log(error);
            }
        );
}

 

  但是要是封裝了怎麼設置我組件的state呢?機智的我想到了個辦法,在組件內部建立一個帶參函數modifyState(),在使AxiosGet()函數時將modifyState()函數做爲參數傳入AxiosGet()並在AxiosGet()內部將res.data做爲參數傳modifyState()從而達到setstate的目的。提及來有點繞,用代碼說話npm

//webservice數據請求函數
function AxiosGet(desinationURL,ApplyNewState){
    axios(
        {
            method: 'get',
            url: desinationURL
        })
        .then(
            res => {
                ApplyNewState(res.data);
            }
        )
        .catch(
            error => {
                console.log(error);
            }
        );
}

  上面是組件外部的數據請求函數,下面的是組件內部的鉤子函數和用於傳入獲取數據的函數json

  modifyState(NewState){
        this.setState(
            {
                data:NewState
            }
        );
    }
    componentDidMount(){
        AxiosGet('http://172.89.1.79/LogisticsSporadicBoardBackEnd/index.asmx/ReportArrivalGoods',
        this.modifyState
        );
    }

  恩,明眼人應該已經看懂了,我巧妙的經過在組件內部將函數傳出的方式完成了state的更新,問題雖然解決了,可是這樣操做着實麻煩,要是能在組件外部更新組件的state就行了。有人要說了,狀態提高啊!爲全部的組件建立一個父組件,在父組件中統一更新狀態並經過props的形式傳入子組件。恩,這確實是個辦法,可是父組件就沒有表達出了特別的意思了,就好像div同樣,沒有語義化,有沒有更好的方式呢?百度搜搜react的state,來了來了,他來了,燈燈燈燈!redux閃亮登場!redux

Redux使用七步走axios

  此處對於redux的知識不作講解了,我懂得也就那樣,redux官網上教程很清晰,能夠直接過去學,我主要講講redux在react中的使用。如標題所說,只須要七步。衆所周知,在redux中,最重要的東西就三個後端

{react-router

動做:action,

動做處理函數:reducer,

狀態倉庫:store

}

想必redux官方教程過了一遍的人都能輕鬆理清其中關係與具體運行吧,那麼問題來了,怎麼在react中把組件們的state和store給他綁定上呢?網上帖子一大堆,可是跟我以前那篇中說的同樣,抄來抄去,沒有真正講到小白的點子上,有的還抄錯了致使讀者誤解,這裏我從小白視角作出最貼切的講解,相信你們聽完手敲一遍也就懂了。我是用create-react-app搭建的開發環境,這裏不作贅述。話很少說,上代碼!目錄結構如圖所示:

 

 

 

第一步:安裝依賴:

npm i redux react-redux -s

第二步:建立action

// /actions/test.js

export const PLUS='PLUS'; export function plusActionCreator(){ return{ type:PLUS } }

第三步:建立reducer

// /reducers/test.js
 import {PLUS} from '../actions/test' const initState={count:0}; export function plusReducer(state=initState,action){ switch(action.type){ case PLUS:{ return 
       { count:state.count+1;//此處返回的state只是plusReducer這個小範圍內的state,理解這一點很重要!!!
       }
    }
    default:return state;
  }
}
 

第四步:建立store

// /index.js

const reducer=combineReducers({plus:plusReducer});//這裏須要傳入json對象才行,對象名錶明來自哪一個reducer var store=createStore(reducer);

  上面是redux部分,你們應該很熟悉了,此時也到了最重要的部分:react和redux的結合。須要說明一下,react的組件咱們如今分爲展現組件和容器組件兩類,展現組件負責界面呈現,容器組件負責爲展現組件管理state。展現組件的全部state經過props傳入。

第五步:建立展現組件

// /index.js

function Test (props){
    return(
        <div>
            <p>總計數:{props.count}</p>
            <button onClick={props.plus}>加一</button>
        </div> 
    );
}

 

第六步:經過react-redux提供的connect方法生成容器組件

// /index.js

const CollectionComponent=connect(
    (state)=>{
        return{
            count:state.plus.count//這裏須要注意,各個小版塊的state是經過combinereducers中命名的json對象名作了分隔的
                    //此處的json對象count與展現組件中的props.count是對應關係
} }, (dispatch)=>{ return{ plus:bindActionCreators(plusActionCreator,dispatch)
       //此處的json對象plus與展現組件中的props.plus方法也是對應關係
} } )(Test);//此處的Test與展現組件名也是對應關係
 

  這裏很關鍵,首先const CollectionComponent,這個CollectionComponent就是咱們所須要的容器組件。

  connect(read,write)(destination)函數有三個參數read、write和destionation(抽象名,爲了方便理解這麼叫),read的目的就是從store中返回咱們要的state,write的目的是傳入action來更新state,destination用來綁定到指定的展現組件。

第七步:經過react-redux提供的Provider組件搭建react和redux數據交互的橋樑

// /index.js

ReactDOM.render(   
<Provider store={store}>//這裏把以前建立的store傳給Provider,這樣store中的state就能傳達到容器組件中了 <CollectionComponent/>//因爲第六步忠已經把展現組件綁定到了容器組件上了,因此此處只需寫容器組件便可   </Provider>   ,document.getElementById('root'));

 


 

 

OVER!經過這個小demo便可完成一個簡單的累加器。最後貼上完整源碼,嘿嘿嘿,yes!

// /reducers/test.js

import {PLUS} from '../actions/test'

const initState={count:0};

export function plusReducer(state=initState,action){
    switch(action.type){
        case PLUS:{
            return {
                count:state.count+1
            }
        }
        default:return state;
    }
}
// /actions/test.js

export const PLUS='PLUS';

export function plusActionCreator(){
    return{
        type:PLUS
    }
}
// /index.js

//react
import React from 'react'
import ReactDOM from 'react-dom'
//redux
import {connect,Provider} from 'react-redux'
import {bindActionCreators,combineReducers,createStore} from 'redux'
import {plusReducer} from './reducers/test'
import {plusActionCreator} from './actions/test'
//呈現部分
function Test (props){
    return(
        <div>
            <p>這裏是count:{props.count}</p>
            <button onClick={props.plus}>加一</button>
        </div> 
    );
}
//redux部分
const reducer=combineReducers({plus:plusReducer});//這裏須要傳入json對象才行
var store=createStore(reducer);

const CollectionComponent=connect(
    (state)=>{
        return{
            count:state.plus.count//這裏須要注意,各個小版塊的state是
                                  //經過combinereducers中命名的json對象名作了分隔的
        }
    },
    (dispatch)=>{
        return{
            plus:bindActionCreators(plusActionCreator,dispatch)
        }
    }
)(Test);

ReactDOM.render(
<Provider store={store}>
     <CollectionComponent/>
</Provider>
,document.getElementById('root'));

最後再給個小彩蛋吧,今天剛搗鼓的react-router的小demo,也是嵌套在上面的代碼中的。

//react
import React from 'react'
import ReactDOM from 'react-dom'
//redux
import {connect,Provider} from 'react-redux'
import {bindActionCreators,combineReducers,createStore} from 'redux'
import {plusReducer} from './reducers/test'
import {plusActionCreator} from './actions/test'
//router
import { BrowserRouter,Switch,Route,NavLink  } from 'react-router-dom';
//呈現部分
function Test (props){
    return(
        <div>
            <p>這裏是count:{props.count}</p>
            <button onClick={props.plus}>加一</button>
        </div> 
    );
}
//redux部分
const reducer=combineReducers({plus:plusReducer});//這裏須要傳入json對象才行
var store=createStore(reducer);

const CollectionComponent=connect(
    (state)=>{
        return{
            count:state.plus.count//這裏須要注意,各個小版塊的state是
                                  //經過combinereducers中命名的json對象名作了分隔的
        }
    },
    (dispatch)=>{
        return{
            plus:bindActionCreators(plusActionCreator,dispatch)
        }
    }
)(Test);

ReactDOM.render(
<Provider store={store}>
    <BrowserRouter >
        <Switch>
            <Route path="/class/classmates">
                <div>QianYingLi,HaoWu,ZhouHuiFan</div>
                <NavLink to="/class" activeClassName="fillInClassNameHere">
                    redirect to class
                </NavLink>
            </Route>
            <Route path="/class">
                <div>高一二</div>
                <NavLink to="/class/classmates" activeClassName="hurray">
                    redirect to classmates
                </NavLink>
            </Route>
            <Route path="/">
                <CollectionComponent/>
            </Route>
        </Switch>
    </BrowserRouter >
</Provider>
,document.getElementById('root'));
相關文章
相關標籤/搜索