基於React+Router+Redux+Sagas+fetch+ant Design +less + es6+mockjs的項目過程總結

app.js是首頁面,路由放此。
sagas在此頁面被引用。
 
import rootSaga from './sagas'
const store = configureStore(initialState)
store.runSaga(rootSaga); 

1)FL.js    
修改對應的接口Path值,便於後期對接口地址的管理。
SupSearch:'/api/Order/supSearch.json',
SupState:'/api/Order/supState.json',
2)sagas  
中間件,只會在應用啓動時調用(但初始啓動的sagas可能會動態的調用其它sagas),用於監聽發起的action,而後決定這個action用來作什麼。
如:1.發起一個異步調用(ajax請求) 2.發起其它的action到store。 3.調用其它的sagas
 
index.js裏面放全部的sagas。
import { watchGetAccountSaga } from './account'
import {supSearch} from './supSearch'
export default function* rootSaga() {
    yield [
        // 更多
        watchGetAccountSaga(),
        supSearch(),
    ]
}
子saga:有兩個Generator函數。其中一個經過while(true),take方法來一直監聽action。
只有當此事件被dispatch則fork第二個Generator函數。(此步驟避免了同時發起多個沒必要要的請求。
只有當view頁面componentWillMount 才觸發此action,發起請求。)
componentWillMount(){  
        this.props.initialDispatch()
    },
import { SUPSEARCHACTION, supSearchSucceed,supSearchFailed} from '../actions/sup'
export function* supSearch() {
    while (true) {
        yield take(SUPSEARCHACTION)
        yield fork(fetchSupSearchApi)
    }
}
第二個Generator方法主要用來生成fetch請求。
任務要被beginTask和endTask包裹。在請求成功以後,將請求到的數據dispatch一個對應的action(成功:supSearchSucceed(res) ) 失敗(supSearchFailed(e) )。
 
function* fetchSupSearchApi(){
    try {
        yield put( beginTask() )
        const response = yield call(fetch, FL.PATH.API.SupSearch)
        const res = yield response.json()
        if (!res) {
            return false
        } else {
            yield put( supSearchSucceed(res) )   (成功)
        }
    } catch (e) {
        yield put( supSearchFailed(e) )   (失敗)
    } finally {
        yield put( endTask() )
    }
}
mockjs也是放在此文件中。
 
// mock 代碼放在 __DEBUG__ 代碼塊內,生產環境會刪除代碼塊
if (__DEBUG__) {
    let data = Mock.mock({
        'Status': '200',
        'Position': '001',
        'ErrorCode': '001',
        'Data|1-10': [{
            'productNumber': /[A-Z][A-Z]\d{3}[a-z]\d{3}/,
            'productName': '@ctitle(3, 5)',
            'supplierName': '@ctitle(3)',
            'productStockStatus|1-100': 1,
            'faceValue|1-1000': 1,
            'productPrice|1-100': 1,
            'type|1-4': 1,
            'averageChargeTime':'@natural(0,200)'+'min',
            'complaintRate':'@natural(0,100)'+'%',
            'successRate': '@natural(0,100)'+'%',
            'today|1-100': 1,
            'week|1-1000':1 ,
            'month|1-10000': 1,
            'purchaseApplyStatus': '@boolean()'
        }]
    });
 
    fetchMock.mock(FL.PATH.API.SupSearch, data);
    // fetchMock.mock(FL.PATH.API.ACCOUNT, 404);
}

 

3)action
在對應的action文件sup.js中,
 
export const SUPSEARCHACTION = 'SUPSEARCHACTION'
export const SUPSEARCH_SUCCEED = 'SUPSEARCH_SUCCEED'
export const SUPSEARCH_FAILED = 'SUPSEARCH_FAILED'

 

分別對應觸發,請求成功、請求失敗的action:
export function supSearchAction(){
    return {
        type:SUPSEARCHACTION
    }
}
export function supSearchSucceed(items){
    return {
        type:SUPSEARCH_SUCCEED,
        items
    }
}
export function supSearchFailed(error) {
    return {
        type: SUPSEARCH_FAILED,
        error,
    }
}

 

 
4)reducer
index.js中爲總reducer。經過import將各個reducer引入進來,經過combineReducer將各個子reducer結合起來。configureStore.js中引入此rootReducer。
 
import supSearch from './supSearch'
import supState from './supState'
 
 
const rootReducer = combineReducers({
    routing: routerReducer,
    supSearch,
    supState,
})
 
export default rootReducer

 

將action的三種type值引入,觸發不一樣的type值會有不一樣的處理。
一、當觸發SUPSEARCHACTION時,將isfetching設爲true,表明開始請求數據。
二、當觸發SUPSEARCH_SUCCEED時,將isfetching設爲false,表明請求完成,成功,並將請求到的參數返回給items,items的值同步到state當中。
三、當觸發SUPSEARCH_FAILED時,將isfetching設爲false,表明請求完成,失敗。返回錯誤。
import {SUPSEARCHACTION,SUPSEARCH_SUCCEED,SUPSEARCH_FAILED} from '../actions/sup'
 
export default function supSearch (state = {}, action) {
    switch (action.type) {
        case SUPSEARCHACTION:
            return {
                ...state,
                isfetching:true,
            }
        case SUPSEARCH_SUCCEED:
            return {
                ...state,
                isfetch:false,
                items: action.items,
            }
        case SUPSEARCH_FAILED:
            return {
                ...state,
                isfetching: false,
                error: action.error,
                };
        default:
            return state
    }
}
 

 

5)containers
用於將state進行處理,處理好的數據經過connect傳遞給component中的view頁面  涉及到reselect(建立選擇器)。
 
import { connect} from 'react-redux'  
import SupSearch from '../components/SupSearch/js/SupSearch'
import {supSearchAction} from '../actions/sup' 
import {createSelector } from 'reselect'
 
const defaultValue = [];
const stateItemSelector = (state) =>state.supSearch.items || defaultValue
const stateSelector = createSelector (
    [stateItemSelector],
    (stateItem) => {
        return stateItem
    }
)
const mapStateToProps = (state) =>{
    return {
        items:stateSelector(state),
    }
}
const mapDispatchToProps = (dispatch) =>{
    return {
        initialDispatch(){
            dispatch(supSearchAction())
        },
    }
}
export default connect(
    mapStateToProps,
    mapDispatchToProps
)(SupSearch)
6)component
此部分即爲view模塊。只有當組件即將被渲染時,才發起action,觸發saga部分的yield take(SUPSEARCHACTION)
initialDispatch方法即爲5)中mapDispatchToProps傳過來的方法。
 
componentWillMount(){
        this.props.initialDispatch()
    },
相關文章
相關標籤/搜索