Redux 的诟病是重复的模块代码太多,各路大佬都开始尝试解决这些问题,Redux-actions 悄然而生。
刚开始使用 Redux-actions 时遇到一些问题,那么专门写一篇博客全面详细的记录 Redux-actions 的使用。
npm install redux-actions
入口
// 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(
,
document.getElementById('root'),
);
App 组件
// 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 (
"action">
);
}
export default connect(
(state) => state,
(dispatch) => {
return {
...bindActionCreators(actions, dispatch),
};
},
)(App);
如果不熟悉 bindActionCreators 的用法可以参考我前面记录的 bindActionCreators & combineReducers 使用记录
action 文件
import { createAction, createActions } from 'redux-actions';
// 通常 action 方式定义
export const normalAction = (params) => {
return {
type: 'ACTIONS',
payload: params,
};
};
reducer 与 store
import { 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 };
后续介绍 redux-actions 方法会修改对应的 action 和 reducer 文件。
// 参数列表
createAction(
type,
payloadCreator = Identity,
?metaCreator
)
action.js
import { 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'));
// 参数列表
createActions(
actionMap,
?...identityActions,
?options
)
action.js
import { 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);
嵌套定义
export const specialActions = createActions({
//增加层级,拓展命名空间
APP: {
ACTION1: (params) => {
return params;
},
ACTION3: (params) => {
return params;
},
},
MY: {
ACTION1: (params) => {
return params;
},
ACTION3: (params) => {
return params;
},
},
});
// 参数列表
createAction(
type,
payloadCreator = Identity,
?metaCreator
)
reducer.js
import { 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 };
image-20201203114905282
// 参数列表
handleActions( reducerMap, defaultState);
import { 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' },
);
顾名思义,合并actions
这个方法是合并 reducer 中 type,使多个action 可以触发同一个 reducer 处理方法。
// 参数列表
combineActions(...types);
actions.js
const { action1, action3 } = createActions({
ACTION1: (params) => {
return params;
},
ACTION3: (params) => {
return params;
},
});
export { action1, action3 };
reducer.js
import { handleActions, combineActions } from 'redux-actions';
import { action1, action3 } from './action';
const specialReducer = handleActions(
{
// action1, action3 都触发该方法
[combineActions(action1, action3)]: (state, action) => {
return { action };
},
},
{}
);
新建 bindActionCreatorsPlus.js
// 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;
}
应用组件 App.js
import 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 (
"action">
);
}
export default connect(
(state) => state,
(dispatch) => {
return {
//使用自定义的 bindActionCreatorsPlus方法处理action
...bindActionCreatorsPlus(actions.actions, dispatch),
};
},
)(App);
嵌套 action.js
export const actions = createActions({
App: {
ACTION1: (params) => {
return params;
},
ACTION3: (params) => {
debugger;
return params;
},
},
});
React进阶教程之状态管理Redux以及React-redux插件(通俗易懂版)
Redux 中间件使用
bindActionCreators & combineReducers 使用记录