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值會有不同的處理。
1、當觸發SUPSEARCHACTION時,將isfetching設為true,代表開始請求數據。
2、當觸發SUPSEARCH_SUCCEED時,將isfetching設為false,代表請求完成,成功,並將請求到的參數返回給items,items的值同步到state當中。
3、當觸發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() },