这可能是一个菜鸟问题。
我对redux传奇的第一次体验。
商店:
import { createStore, applyMiddleware, compose } from 'redux';
import createSagaMiddleware from 'redux-saga';
import { createLogger } from 'redux-logger';
import rootReducer from '../reducers/RootReducer';
import rootSagas from '../sagas/RootSaga';
const enhancers = [];
const sagaMiddleware = createSagaMiddleware(),
logger = createLogger(),
initialState = {},
middleware = [ logger, sagaMiddleware ];
if ( process.env.NODE_ENV === 'development' ) {
const devToolsExtension = window.__REDUX_DEVTOOLS_EXTENSION__;
if ( typeof devToolsExtension === 'function' ) {
enhancers.push( devToolsExtension() );
}
}
const composedEnhancers = compose(
applyMiddleware( ...middleware ),
...enhancers
);
const store = createStore( rootReducer, initialState, composedEnhancers );
sagaMiddleware.run( rootSagas );
export default store;
动作:DashboardAction.js
import actionTypes from '../constants/ActionTypes';
export function getDataForDashboard( response ) {
console.log( 'in the action for dashboard' );
return {
type: actionTypes.GET_DATA_FOR_DASHBOARD,
payload: response
};
}
export function getDataForDashboardSuccess( response ) {
return {
type: actionTypes.GET_DASHBOARD_DATA_SUCCESS,
payload: response
};
}
export function getDataForDashboardError( error ) {
return {
type: actionTypes.GET_DASHBOARD_DATA_ERROR,
payload: error
};
}
常量:ActionTypes.js
export default {
GET_DATA_FOR_DASHBOARD: 'GET_DATA_FOR_DASHBOARD',
GET_DASHBOARD_DATA_SUCCESS: 'GET_DASHBOARD_DATA_SUCCESS',
GET_DASHBOARD_DATA_ERROR: 'GET_DASHBOARD_DATA_ERROR'
};
The Saga:RootSaga.js
import { all } from 'redux-saga/effects';
import * as dashboardSagas from './DashboardSaga';
export default function* root() {
yield all( dashboardSagas.GetDataForDashboard() );
}
DashboardSaga.js
import { takeEvery } from 'redux-saga';
import { call, put } from 'redux-saga/effects';
import actionTypes from '../constants/ActionTypes';
import { getData } from '../services/DashboardService';
import {
getDataForDashboardSuccess,
getDataForDashboardError
} from '../actions/DashboardActions';
export function* GetDataForDashboard( action ) {
console.log( 'hello from inner method' );
try {
const response = yield call( getData, action );
//if ( response.id ) {
yield put( getDataForDashboardSuccess( response ) );
// }
} catch ( error ) {
yield put( getDataForDashboardError( error ) );
}
}
export function* watchGetDataForDashboard() {
console.log( 'hello from watcher' );
yield takeEvery( actionTypes.GET_DATA_FOR_DASHBOARD, GetDataForDashboard );
}
Reducer:DashboardReducer.js / *禁止禁用未使用的变量* /
import actionTypes from '../constants/ActionTypes';
const initialState = {
error: false,
dashboard: {
orderdashboardmodel: {
rfs: '0',
pending: '0',
total: '0'
},
sitesdashboardmodel: {
up: '0',
down: '0',
total: '0',
notmonitored: '0'
},
support: {
open: '0',
late: '0',
escalated: '0'
}
}
};
function getDataForDashboard( state ) {
console.log( 'it comes here' );
return null;
}
function getDashboardSuccess( state, action ) {
console.log( 'IN SUCCESS' );
console.log( action.payload );
return {
...state,
dashboard: {
orderdashboardmodel: {
rfs: action.payload.dashboardModel.Order.RFS,
pending: action.payload.dashboardModel.Order.Pending,
total: action.payload.dashboardModel.Order.Total
},
sitesdashboardmodel: {
up: action.payload.dashboardModel.Sites.Up,
down: action.payload.dashboardModel.Sites.Down,
total: action.payload.dashboardModel.Sites.Total,
notmonitored: action.payload.dashboardModel.Sites.NotMonitored
},
support: {
open: action.payload.dashboardModel.Support.Open,
late: action.payload.dashboardModel.Support.Late,
escalated: action.payload.dashboardModel.Support.Escalated
}
}
};
}
function getDashboardError( state = initialState, action ) {
console.log( action.payload );
return {
...state,
error: true
};
}
export default function DashboardReducer( state = initialState, action ) {
console.log( 'IN REDUCER' );
console.log( action );
switch ( action.type ) {
case actionTypes.GET_DATA_FOR_DASHBOARD:
console.log( 'in the call for dashboard' );
getDataForDashboard( state );
console.log( 'in the call exit' );
break;
case actionTypes.GET_DASHBOARD_DATA_SUCCESS:
console.log( 'in the success call initator' );
getDashboardSuccess( state, action );
break;
case actionTypes.GET_DASHBOARD_DATA_ERROR:
getDashboardError( state, action );
break;
default:
return state;
}
}
发起呼叫的文件:Dashboard.js
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { Colors } from '../../common/themes';
import Globe from '../../common/assets/images/globe.png';
import DashboardCard from './DashboardCard';
import { DashboardData } from './DashboardData';
import { getDataForDashboard } from '../actions/DashboardActions';
class Dashboard extends React.Component {
componentDidMount() {
console.log( 'called before' );
this.props.getDataForDashboard( 'hello' );
console.log( 'called after' );
}
render() {
return (
<div>some html here</div>
);
}
}
const mapStateToProps = state => ( { dashboard: state.dashboard } );
const mapDispatchToProps = dispatch =>
bindActionCreators( { getDataForDashboard }, dispatch );
export default connect(
mapStateToProps,
mapDispatchToProps
)( Dashboard );
Package.json
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.0-14",
"@fortawesome/free-solid-svg-icons": "^5.1.0-11",
"@fortawesome/react-fontawesome": "0.1.0-11",
"aws-amplify": "^1.0.4",
"aws-amplify-react": "^1.0.4",
"axios": "^0.18.0",
"bootstrap": "^4.1.3",
"chroma-js": "^1.3.7",
"d3": "^5.5.0",
"i": "^0.3.6",
"npm": "^6.4.0",
"react": "^16.4.1",
"react-dom": "^16.4.1",
"react-loadable": "^5.4.0",
"react-motion": "^0.5.2",
"react-particles-js": "^2.3.0",
"react-redux": "^5.0.7",
"react-router-dom": "^4.3.1",
"react-simple-maps": "^0.12.1",
"reactstrap": "^6.3.1",
"redux": "^4.0.0",
"redux-logger": "^3.0.6",
"redux-saga": "^0.16.0"
},
"devDependencies": {
"babel-core": "^6.26.3",
"babel-eslint": "^8.2.6",
"babel-loader": "^7.1.5",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.7.0",
"babel-preset-flow": "^6.23.0",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"babel-preset-stage-2": "^6.24.1",
"clean-webpack-plugin": "^0.1.19",
"css-loader": "^1.0.0",
"dotenv": "^6.0.0",
"eslint": "^5.2.0",
"eslint-plugin-import": "^2.13.0",
"eslint-plugin-react": "^7.10.0",
"file-loader": "^1.1.11",
"html-webpack-plugin": "^3.2.0",
"jest": "^23.4.2",
"open-browser-webpack-plugin": "0.0.5",
"prettier": "^1.14.0",
"prettier-eslint": "^8.8.2",
"radium": "^0.24.1",
"style-loader": "^0.21.0",
"webpack": "^4.12.2",
"webpack-cli": "^3.0.8",
"webpack-dev-server": "^3.1.4"
},
"jest": {
"verbose": true,
"testURL": "http://localhost/"
}
问题 佐贺从未被称为。 出现以下错误:
Uncaught Error: Given action "GET_DATA_FOR_DASHBOARD", reducer "dashboardReducer" returned undefined. To ignore an action, you must explicitly return the previous state. If you want this reducer to hold no value, you can return null instead of undefined
我尝试了reducer中的每个组合,但是这个错误永远不会消失。也许是一双新鲜的眼睛可以挑选出我所缺少的东西。
答案 0 :(得分:2)
根据docs
reduceer是一个纯函数,它接受上一个状态和一个动作,然后返回下一个状态。
然后您会看到这是因为您正在使用switch语句而不是在DashboardReducer.js
中返回新状态。它应该看起来像这样:
export default function DashboardReducer( state = initialState, action ) {
switch ( action.type ) {
case actionTypes.GET_DATA_FOR_DASHBOARD:
// note: the function you call returns null. That might not be
// what you are trying to do so just be aware of that.
return getDataForDashboard( state );
case actionTypes.GET_DASHBOARD_DATA_SUCCESS:
return getDashboardSuccess( state, action );
case actionTypes.GET_DASHBOARD_DATA_ERROR:
return getDashboardError( state, action );
default:
return state;
}
}