原因一:使用異步actions時,沒有配置redux-thunk這個中間件
中間件就是一個函數,對store.dispatch方法進行了改造,在發出 Action 和執行 Reducer 這兩步之間,添加了其他功能。
import { applyMiddleware, createStore } from 'redux';
import createLogger from 'redux-logger';
const logger = createLogger();
const store = createStore(
reducer,
applyMiddleware(logger)
);
上面代碼中,redux-logger提供一個生成器createLogger,可以生成日志中間件logger。然后,將它放在applyMiddleware方法之中,傳入createStore方法,就完成了store.dispatch()的功能增強。
const store = createStore(
reducer,
applyMiddleware(thunk, promise, logger)
);
applyMiddleware 是Redux 的原生方法,作用是將所有中間件組成一個數組,依次執行。
原因二:調用action方法時,方法體內部并沒有調用dispatch。
/**
* 加載路由或iframe
*
* @param menu 需要加載的菜單
*/
export function onLoadMain(menu) {
let routeUrl = menu.routeurl;
let url = menu.url;
console.log("routeUrl : ",routeUrl);
if (routeUrl) {
weaHistory.push({pathname: routeUrl});
document.getElementById('e9frameMain').style.visibility = 'hidden';
document.getElementById('e9routeMain').style.display = 'block';
// let mainframe = document.getElementById('mainFrame');
// mainframe.src = 'about:blank';
document.getElementById('mainFrame').src = 'about:blank';
} else if (url && url != 'javascript:void(0);') {
let target = menu.target || 'mainFrame';
if ('mainFrame' != target) {
window.open(url, target);
} else {
// let mainframe = document.getElementById('mainFrame');
// mainframe.src = url;
document.getElementById('mainFrame').src = url;
document.getElementById('e9frameMain').style.visibility = 'visible';
document.getElementById('e9routeMain').style.display = 'none';
}
}
}
以上是一個普通的function,放在action的js文件中,如果你使用了如下方式去調用這個方法,雖然能成功調用,但在配置了redux-thunk這個中間件的情況下,你發起的任何action方法,都會走thunk這個中間件,一旦方法體內沒有dispatch這個方法,則會報Actions must be plain objects. Use custom middleware for async actions這個異常。
import * as themeActions from '../../../actions/theme';
handleClick(e) {
const {actions}=this.props;
let urlParams= {
iframeUrl: e.key,
routeUrl:e.item.props.routeurl
}
actions.updateMenusUrl(urlParams);*/
let menuInfo={
routeurl:e.item.props.routeurl,
url: e.key,
target:'mainFrame'
}
//通過派生action的形式來調用這個方法
actions. onLoadMain(menuInfo);
function mapStateToProps(state) {
const {middleTheme} = state;
return {
backEndMenuUrl: middleTheme.get('backEndMenuUrl'),
columnMenuInfo:middleTheme.get('columnMenuInfo')
}
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(themeActions, dispatch)
};
}
module.exports = connect(mapStateToProps, mapDispatchToProps)(E9LeftMenusTree);
所以常規function最好通過import導入的形式去調用就OK了,如下:
import {onLoadMain} from '../../../actions/theme';
handleClick(e) {
const {actions}=this.props;
let urlParams= {
iframeUrl: e.key,
routeUrl:e.item.props.routeurl
}
actions.updateMenusUrl(urlParams);*/
let menuInfo={
routeurl:e.item.props.routeurl,
url: e.key,
target:'mainFrame'
}
//常規import組件形式調用function
onLoadMain(menuInfo);
}
最后分享下我在解決這個問題中參考的阮大大的關于redux中間件的介紹:Redux中間件和異步操作