Redux 的書寫分離
從 Redux 官方示例開始涕癣,我們就采用了 actions 和 reducers 分開文件夾來維護(hù)的思路哗蜈。
但是在實(shí)際業(yè)務(wù)中,大部分場景下一個(gè) action 觸發(fā)的 reducer 是在一個(gè)子 reducer 下坠韩。
這里其實(shí)引入了 combineReducers 工具來分離大型的 store 數(shù)據(jù)距潘。
然而飽受詬病的正是一個(gè)用戶操作開發(fā)起來要寫多個(gè)文件,component, action, reducer, api... 非常不方便只搁,所以我們考慮將 action 和 reducer 合并在一個(gè)文件中書寫音比。
于是我們移除 actions 和 reducers 文件夾,新建一個(gè) redux 目錄氢惋,里面放業(yè)務(wù)文件洞翩,如:
// newsList.js
import getNewsAPI from '../api/getNews';
import createReducer from '../lib/createReducer';
import processErrors from '../lib/processErrors';
import * as actionTypes from '../config/actionTypes';
const defaultState = {
loading: false,
list: [],
};
export default createReducer(defaultState, {
[actionTypes.GET_MORE_NEWS]: (state, action) => {
switch (action.status) {
case 'loading':
return { ...state, loading: true };
case 'success':
return { ...state, loading: false, list: [ ...state.list, ...action.payload ] };
case 'error':
return { ...state, loading: false };
}
return state;
},
[actionTypes.CLEAR_NEWS_LIST]: (state, action) => {
return { ...state, list: [] };
},
});
export const getMoreNews = () => {
return async(dispatch) => {
try {
dispatch({
type: actionTypes.GET_MORE_NEWS,
status: 'loading',
});
const list = await getNewsAPI();
dispatch({
type: actionTypes.GET_MORE_NEWS,
status: 'success',
payload: list,
});
} catch (ex) {
dispatch({
type: actionTypes.GET_MORE_NEWS,
status: 'error',
});
processErrors(ex);
}
};
};
export const clearNewsList = () => {
return {
type: types.CLEAR_NEWS_LIST,
};
};
這里我們利用 export default 和 export cont 來區(qū)分 reducer 和 action,外部使用 reducer 時(shí) import newsListReducers from './newsList';
得到的 newsListReducers
是一個(gè)方法焰望,并不包含 getMoreNews
和 clearNewsList
兩個(gè)方法骚亿,比較純凈。
同時(shí)使用 action 時(shí)通過 import { getMoreNews, clearNewsList } from '../redux/newsList';
拿到 function熊赖。
action 和 reducer 的對應(yīng)關(guān)系
action 和 reducer 并不一定是一一對應(yīng)的来屠,部分場景下一個(gè) action 可以觸發(fā)多個(gè) reducer 的處理。
因此 actionTypes 定義在 config 文件中作為常量管理可以方便在多個(gè)文件中使用震鹉。
redux-thunk 的 dispatch 并不一定是必須的
在上面的例子中俱笛,我們試用了 redux-thunk 中間件來支持異步 action,并且推遲 action 的執(zhí)行传趾。有些人會以為這里寫同步 action 的時(shí)候也需要嵌套一層 dispatch
export const clearNewsList = () => {
return (dispatch) => {
dispatch({
type: types.CLEAR_NEWS_LIST,
});
};
};
這種寫法有點(diǎn)多余侵佃,我們可以直接 return action 對象钓账。
Redux 的性能問題
很多人都認(rèn)為 react 組件的 props 和 state 沒有變更的時(shí)候不會執(zhí)行組件的 render 方法,但是這個(gè)看法是不正確的。默認(rèn)的不从,只要父組件 render 方法執(zhí)行了,子組件的 render 是會執(zhí)行的匹舞。
除非我們在子組件上實(shí)現(xiàn)了 shouldComponentUpdate 方法揩徊,這個(gè)可以避免作組件多余的 render 計(jì)算。react-redux 提供的 connect 正是實(shí)現(xiàn)了這個(gè)方法蝶棋,因此 connect 用得越多卸亮,項(xiàng)目性能越好。