redux樣板程式碼簡化寫法

看風景就發表於2018-08-24

直接使用redux,要寫很多樣板程式碼,大量的actiontype,actionCreator。
一個非同步的方法要寫三個actiontype,三個actionCreator,十分繁瑣。
下面是本人使用的一種簡化寫法,使用陣列動態生成一些action和actionCreator,具有參考價值。

action-type.js

export const asynctypes = [
    'getCateList', 
    'getArticleList',  
    'searchArticles',       
    'getArticleDetail', 
]

export const synctypes = [
    '@@router/LOCATION_CHANGE'
]

export const types = {};

asynctypes.forEach(item => {
    types[item + '.start'] = item + '.start';
    types[item + '.ok'] = item + '.ok';
    types[item + '.error'] = item + '.error';
});

synctypes.forEach(item => {
    types[item] = item;
});

synctypes生成同步的actiontype,asynctypes生成非同步的actiontype,字串只在陣列中宣告一次,減少書寫量

action.js

import {asynctypes} from './action-type';
import {createAction} from 'redux-actions';

function fCreateActionsAsync(aType,fCreateAction){
    const oResult = {};
    aType.forEach(item => {
        oResult[item + 'Start'] = fCreateAction(item + '.start');
        oResult[item + 'Ok'] = fCreateAction(item + '.ok');
        oResult[item + 'Error'] = fCreateAction(item + '.error');
    });
    return oResult;
}

export default fCreateActionsAsync(asynctypes,createAction);

匯出的是通過asynctypes生成的三個actionCreator的集合,此集合可以直接在bindActionCreators函式中直接使用,
在元件中可以直接呼叫生成的action方法:

元件article.jsx

import acts from 'index/redux/actions';

export default connect(
    (state,props) => { return {data: state.article.data,currentCate:fCurrentCate(state,props)} },
    dispatch => { return {actions: bindActionCreators(acts,dispatch)} }
)(Article);

在元件中使用actions.getCateListStart就可以開始一個非同步呼叫了。

start是個開始,專案中使用了redux-saga來自動喚起下面的非同步呼叫,非同步完成後自動呼叫ok或error的action。

//根saga中監控所有的非同步呼叫
export default function* rootSaga(){
    yield [
        fork(wacthArticleDetail),
        fork(watchCateList),
        fork(watchActicleList),
        fork(watchSearchAtricles)
    ]
}
//監控到非同步start呼叫,自動喚起非同步呼叫
function* wacthArticleDetail(){
    yield takeEvery(actions.getArticleDetailStart,fGetArticleDetailAsync);
}

//非同步呼叫結束自動喚起Ok或者error的action
function* fGetArticleDetailAsync(action) {
    try{
        const articleId = action.payload.articleId;
        const article = yield call(getArticleDetail,articleId);
        yield put(actions.getArticleDetailOk(article));
    }
    catch(err){
        yield put(actions.getArticleDetailError(err))
    }
}

相關文章