Redux 的诟病是重复的模块代码太多,各路大佬都开始尝试解决这些问题,Redux-actions 悄然而生。
刚开始使用 Redux-actions 时遇到一些问题,那么专门写一篇博客全面详细的记录 Redux-actions 的使用。
javascriptnpm install redux-actions
javascript// index.jsx import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; import { Provider } from 'react-redux'; import { store } from './store'; ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root'), );
javascript// App.jsx import React, { Component } from 'react'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import * as actions from './action'; import './App.css'; function App(props) { console.log('!! props 📢:', props); return ( <div className="action"> <button onClick={() => { props.normalAction('测试'); props.normalAction('测试'); }} > 测试Action </button> </div> ); } export default connect( (state) => state, (dispatch) => { return { ...bindActionCreators(actions, dispatch), }; }, )(App);
🏁 如果不熟悉 bindActionCreators 的用法可以参考我前面记录的 bindActionCreators & combineReducers 使用记录
action 文件
javascriptimport { createAction, createActions } from 'redux-actions'; // 通常 action 方式定义 export const normalAction = (params) => { return { type: 'ACTIONS', payload: params, }; };
javascriptimport { createStore } from 'redux'; const reducer = (state, action) => { switch (action.type) { case 'ACTIONS': return { ...state, ACTIONS: action.payload }; default: return state; } }; const store = createStore(reducer, {}); export { store };
createAction
javascript// 参数列表 createAction( type, payloadCreator = Identity, ?metaCreator )
javascriptimport { createAction, createActions } from 'redux-actions'; export const normalAction = (params) => { return { type: 'ACTIONS', payload: params, }; }; export const specialAction = createAction( 'ACTIONS', (params) => { return params; }, (meta) => { return { admin: true }; }, ); console.log('normalAction', normalAction('levenx')); console.log('specialAction', specialAction('levenx'));
javascript// 参数列表 createActions( actionMap, ?...identityActions, ?options )
javascriptimport { createActions } from 'redux-actions'; // 同时生成多个 action 方法,并集合到一个对象中, // !!🏁 但是这种方式生成的action不能通过 bindActionCreators 方法来绑定 // 具体问题分析与解决方案可以参考 https://blog.csdn.net/m0_37890289/article/details/110493826 // 文末贴出问题解决代码 export const specialActions = createActions({ //只考虑 payload ACTION1: (params) => { return params; }, // 处理meta ACTION2: [ (params) => { return params; }, (meta) => { return { meta }; }, ], ACTION3: (params) => { return params; }, }); console.log('specialActions', specialActions);
javascriptexport const specialActions = createActions({ //增加层级,拓展命名空间 APP: { ACTION1: (params) => { return params; }, ACTION3: (params) => { return params; }, }, MY: { ACTION1: (params) => { return params; }, ACTION3: (params) => { return params; }, }, });
javascript// 参数列表 createAction( type, payloadCreator = Identity, ?metaCreator )
javascriptimport { createStore } from 'redux'; import { handleAction } from 'redux-actions'; // 正常使用方式 const specialReducer = handleAction( 'ACTIONS', (state, { type, payload, meta }) => { debugger; return { payload }; }, { init: 'levenx' }, ); // 处理 action 错误情况使用这种方式 const specialReducer = handleAction( 'ACTIONS', { next(state, action) { return { payload }; }, throw(state, action) { return { error }; }, }, { init: 'levenx' }, ); // console.log('📢 specialReducer', specialReducer); const store = createStore(specialReducer, {}); export { store };
javascript// 参数列表 handleActions( reducerMap, defaultState);
javascriptimport { handleActions } from 'redux-actions'; const specialReducer = handleActions( { ACTION1: (state, action) => { return { levenx: '1' }; }, ACTIONS2: { next(state, action) { return { levenx: '1' }; }, throw(state, action) { return { levenx: '1' }; }, }, }, { INIT_DATA: 'levenx' }, );
javascript// 参数列表 combineActions(...types);
javascriptconst { action1, action3 } = createActions({ ACTION1: (params) => { return params; }, ACTION3: (params) => { return params; }, }); export { action1, action3 };
javascriptimport { handleActions, combineActions } from 'redux-actions'; import { action1, action3 } from './action'; const specialReducer = handleActions( { // action1, action3 都触发该方法 [combineActions(action1, action3)]: (state, action) => { return { action }; }, }, {} );
javascript// bindActionCreatorsPlus.js import { bindActionCreators } from 'redux'; export default function bindActionCreatorsPlus(actions, dispatch) { if (typeof actions !== 'object' || !actions) { throw new Error('invalid actions'); } let result = {}; for (let key in actions) { if (actions.hasOwnProperty(key)) { const creator = actions[key]; if (typeof creator === 'object' && creator) { //递归执行 result[key] = bindActionCreatorsPlus(creator, dispatch); } else if (typeof creator === 'function') { result[key] = bindActionCreators(creator, dispatch); } } } return result; }
javascriptimport React, { Component } from 'react'; import { connect } from 'react-redux'; import bindActionCreatorsPlus from './bindActionCreatorsPlus'; import * as actions from './action'; function App(props) { console.log('!! props 📢:', props); return ( <div className="action"> </div> ); } export default connect( (state) => state, (dispatch) => { return { //使用自定义的 bindActionCreatorsPlus方法处理action ...bindActionCreatorsPlus(actions.actions, dispatch), }; }, )(App);
javascriptexport const actions = createActions({ App: { ACTION1: (params) => { return params; }, ACTION3: (params) => { debugger; return params; }, }, });
参考
Redux相关文章推荐
嵌套 action 绑定组件方案
combineActions
handleActions
handleAction
createActions
方法列表
后续介绍 redux-actions 方法会修改对应的 action 和 reducer 文件。
reducer 与 store
App 组件
入口