错误:“预计减速器是一个功能。”当`reducer`绝对是一个函数

时间:2018-03-23 22:14:29

标签: redux react-redux

在测试过程中,我发现了异常:

Expected the reducer to be a function.

但它没有意义。 reducer的类型绝对是function。但是,输出也会发生一些奇怪的事情:

 PASS  src/App.test.js
  ● Console

    console.log src/reducers.js:8
      --- searchResultsReducer: function
    console.log src/store.js:12
      --- 6666: createStore, rootReducer: function
    console.log node_modules/redux/lib/createStore.js:54
      --- 1111 redux/lib/creatStore: typeof reducer: function
    console.log node_modules/redux/lib/createStore.js:66
      --- 5555 redux/lib/creatStore: typeof reducer: function
    console.log node_modules/redux/lib/applyMiddleware.js:38
      --- 7777 typeof reducer: function
    console.log node_modules/redux/lib/createStore.js:54
      --- 1111 redux/lib/creatStore: typeof reducer: function
    console.log node_modules/redux/lib/createStore.js:70
      --- 2222 redux/lib/creatStore: typeof reducer: function
    console.log node_modules/redux/lib/createStore.js:72
      --- 3333 redux/lib/creatStore: typeof reducer: function
    console.log node_modules/redux/lib/applyMiddleware.js:40
      --- 8888 typeof reducer: function

 FAIL  src/actions/querySelector.test.js
  ● Test suite failed to run

    Expected the reducer to be a function.

      at createStore (node_modules/redux/lib/createStore.js:77:11)
      at node_modules/redux/lib/applyMiddleware.js:39:19
      at createStore (node_modules/redux/lib/createStore.js:67:33)
      at Object.<anonymous> (src/store.js:13:54)
      at Object.<anonymous> (src/actions/search.js:4:14)
      at Object.<anonymous> (src/reducers/search.js:1:220)
      at Object.<anonymous> (src/reducers.js:5:15)
      at Object.<anonymous> (src/actions/querySelector.test.js:7:17)
          at <anonymous>

Test Suites: 1 failed, 1 passed, 2 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        5.845s
Ran all test suites matching /a/.

Watch Usage: Press w to show more.

这些console.log行中的每一行都显示减速器的类型为function。但是,--- 4444行永远不会打印,但Error肯定会被抛出。

以下是console.log函数的createStore()语句:

node_modules/redux/lib/createStore.js

// [... snip ...]

function createStore(reducer, preloadedState, enhancer) {
  var _ref2;

  console.log('--- 1111 redux/lib/creatStore: typeof reducer:', typeof reducer);

  if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
    enhancer = preloadedState;
    preloadedState = undefined;
  }

  if (typeof enhancer !== 'undefined') {
    if (typeof enhancer !== 'function') {
      throw new Error('Expected the enhancer to be a function.');
    }

    console.log('--- 5555 redux/lib/creatStore: typeof reducer:', typeof reducer);
    return enhancer(createStore)(reducer, preloadedState);
  }

  console.log('--- 2222 redux/lib/creatStore: typeof reducer:', typeof reducer);
  if (typeof reducer === 'function') {
    console.log('--- 3333 redux/lib/creatStore: typeof reducer:', typeof reducer);
  }

  if (typeof reducer !== 'function') {
    console.log('--- 4444 redux/lib/creatStore: typeof reducer:', typeof reducer);
    throw new Error('Expected the reducer to be a function.');
  }

// [... snip ...]

正如您所看到的,当--- 3333打印reducer的类型为function时,比较应该导致false,而不是抛出异常,但它会抛出无论如何都是例外,甚至不打印--- 4444输出行。

console.log语句发生了什么,为什么没有正确检测到reducer的类型?

以下是代码的其余部分:

src/App.test.js

import React from 'react';
import ReactDOM from 'react-dom';

import App from './App';
import { Provider } from 'react-redux';
import { store } from './store';

it('renders without crashing', () => {
  const div = document.createElement('div');

  ReactDOM.render(
    <Provider store={store}>
      <App />
    </Provider>,
    div
  );
});

src/actions/querySelector.test.js

import { Map } from 'immutable';

import * as actions from './querySelector';
import * as types from './querySelector';
import { rootReducer } from '../reducers';

describe('actions', () => {

  it('should select a query', () => {
    expect(1).equalTo(1);
  });
});

src/reducers.js

import { combineReducers } from 'redux';

import { chartsReducer } from './reducers/charts';
import { errorsReducer } from './reducers/errors';
import { searchResultsReducer } from './reducers/search';
import { querySelectorReducer } from './reducers/querySelector';

console.log('--- searchResultsReducer:', typeof searchResultsReducer);

export const rootReducer = combineReducers({
  charts: chartsReducer,
  errors: errorsReducer,
  search: searchResultsReducer,
  querySelector: querySelectorReducer,
});

src/reducers/querySelector.js

import { Map } from 'immutable';

export const querySelectorReducer = (state = {queries: Map()}, action) => {
  return state;
}

src/components/QuerySelector.js

import React from 'react';
import { Component } from 'react';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';

class QuerySelector extends Component {
  static propTypes = {
    queries: ImmutablePropTypes.map.isRequired,
    onSelectQuery: PropTypes.func.isRequired,
    onClickManage: PropTypes.func.isRequired,
  };

  render() {
    return (<div/>);
  }
}

export default QuerySelector;

src/containers/QuerySelectorRedux.js

import { connect } from 'react-redux';
import QuerySelector from '../components/QuerySelector';

import {
  selectQuery,
  manageQueries,
} from '../actions/querySelector';

export const mapStateToProps = state => {
  return {
    queries: state.querySelector.queries,
  };
};

export const mapDispatchToProps = dispatch => {
  return {
    onSelectQuery: id => {
      dispatch(selectQuery(id));
    },
    onClickManage: () => {
      dispatch(manageQueries());
    },
  };
};

const QuerySelectorRedux = connect(
  mapStateToProps,
  mapDispatchToProps,
)(QuerySelector);

export default QuerySelectorRedux;

1 个答案:

答案 0 :(得分:0)

这是因为我的测试脚本导入了rootReducer