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

我個人粗淺的理解是:
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)的就是輸入輸出的東西。輸入框內(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),
-redux 集中管理狀態(tài)(數(shù)據(jù))
-component 專注于React 展示組件部分
-containers 集中處理React與redux交互的部分
此外,redux還可以處理一些異步請求。這樣的話??梢宰龅絛ata 和view 的管理分離,增強了工程結(jié)構(gòu)的可讀性與可維護(hù)性。