mapDispatchToProps error: component is receiving an object but function expected

mapDispatchToProps error: component is receiving an object but function expected

我对 React 生态系统完全陌生。为了更好地理解 React saga,我创建了一个小项目,它在屏幕上显示一个值,5 秒后它是一个 saga 函数,应该从 useEffect 调用并更改该值。我在 saga 和动作函数中放置了一些日志消息。好像没有调用监听器

constants.js

export const ATTEMPT_DELAY = 'app/SupportPage/ATTEMPT_DELAY';
export const DELAY_SUCCESS = 'app/SupportPage/DELAY_SUCCESS';
export const DELAY_ERROR = 'app/SupportPage/DELAY_SUCCESS';

action.js

import { ATTEMPT_DELAY, DELAY_SUCCESS, DELAY_ERROR } from './constants';

export function attempDelay() {
  console.log('attempt delay action called');
  return {
    type: ATTEMPT_DELAY,
  };
}

export function delaySuccess(value) {
  console.log('delay success action called');
  return {
    type: DELAY_SUCCESS,
    value,
  };
}

export function delayError() {
  return {
    type: DELAY_ERROR,
  };
}

saga.js

import { takeLatest, put } from 'redux-saga/effects';
import { ATTEMPT_DELAY } from './constants';
import { delaySuccess, delayError } from './actions';

export function* delayListener() {
  yield takeLatest(ATTEMPT_DELAY, delay);
}

export function* delay() {
  console.log('delay saga called')
  const value = 10;
  try {
    yield put(delaySuccess(value));
  } catch (e) {
    yield put(delayError);
  }
}

reducer.js

import produce from 'immer';
import { ATTEMPT_DELAY, DELAY_SUCCESS, DELAY_ERROR } from './constants';

export const initialState = {
  value: 5,
  isLoading: false,
};

const supportPageReducer = (state = initialState, action) =>
  // eslint-disable-next-line no-unused-vars
  produce(state, draft => {
    // eslint-disable-next-line default-case
    switch (action.type) {
      case ATTEMPT_DELAY:
        draft.isLoading = true;
        break;
      case DELAY_SUCCESS:
        draft.value = action.value || console.log('setting value');
        break;
      case DELAY_ERROR:
        draft.isLoading = false;
        break;
      default:
        break;
    }
  });

export default supportPageReducer;

index.js

import React, { memo, useEffect } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Helmet } from 'react-helmet';
import { FormattedMessage } from 'react-intl';
import { createStructuredSelector } from 'reselect';
import { compose } from 'redux';

import { useInjectSaga } from 'utils/injectSaga';
import { useInjectReducer } from 'utils/injectReducer';
import makeSelectSupportPage from './selectors';
import reducer from './reducer';
import { delayListener } from './saga';
import { attempDelay } from './actions';
import messages from './messages';

export function SupportPage({ supportPage: { isLoading, value }, delay }) {
  useInjectReducer({ key: 'supportPage', reducer });
  useInjectSaga({ key: 'supportPage', saga: delayListener });

  useEffect(() => {
    setTimeout(() => {
      console.log('delay called');
      delay();
    }, 5000);
  });
  return (
    <div>
      <Helmet>
        <title>SupportPage</title>
        <meta name="description" content="Description of SupportPage" />
      </Helmet>
      <FormattedMessage {...messages.header} />
      <h1>{isLoading ? 'loading' : 'not loading'}</h1>
      <h1>{value}</h1>
    </div>
  );
}

SupportPage.propTypes = {
  supportPage: PropTypes.object,
  delay: PropTypes.func,
};

const mapStateToProps = createStructuredSelector({
  supportPage: makeSelectSupportPage(),
});

function mapDispatchToProps(dispatch) {
  return {
    delay: dispatch(attempDelay()),
  };
}

const withConnect = connect(
  mapStateToProps,
  mapDispatchToProps,
);

export default compose(
  withConnect,
  memo,
)(SupportPage);

当我在浏览器中打开控制台时,我在从 useEffect 调用 delay() 之前看到了日志,并且出现错误“Uncaught ReferenceError: delay is not defined at eval” 我试着用谷歌搜索这个错误,但没有得到任何与 redux-saga 相关的信息。 在 运行 项目之后,当我进行更改并点击保存时,我注意到了一些事情,它重建了项目,然后 saga 被调用并且所有日志消息都在那里并且值按预期更改。 不知道怎么回事!!!

我发现了我的错误。

function mapDispatchToProps(dispatch) {
  return {
    delay: dispatch(attempDelay()),
  };
}

这里我调用 dispatch 并将 dispatch 的 return 值映射到 delay 对象。它应该是一个函数。

更正为:

delay: () => dispatch(attempDelay()),