Почему я получаю заданное действие «Редуктор […] вернулся неопределенным во время инициализации» во время загрузки приложения? - PullRequest
0 голосов
/ 24 августа 2018

Это может быть вопрос новичка.

Мой первый опыт с сагой на основе редукса.

Магазин:

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'
};

Сага: 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 );
}

Редуктор: DashboardReducer.js / * eslint-disable no-unused-vars * /

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

Я перепробовал каждую комбинацию в редукторе, но эта ошибка никогда не возникает.Может быть, свежая пара глаз может выбрать то, что мне не хватает.

1 Ответ

0 голосов
/ 24 августа 2018

Согласно документам

Редуктор - это чистая функция, которая принимает предыдущее состояние и действие и возвращает следующее состояние.

Затем вы можете видеть, что это потому, что вы отказываетесь от своего оператора 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;
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...