首页 > 解决方案 > 为什么将 react-redux 与 typescript 一起使用时,连接的高阶组件中连接的包装组件的调度属性未定义?

问题描述

我是正在努力解决以下问题的新用户。我有一个将属性注入到包装组件的高阶组件(Hoc)。HoC 本身返回一个 React.ComponentClass,它通过 map 和 dispatch 属性连接到 redux 存储。

我正在尝试将 HoC 与也连接到 redux 存储的组件一起使用。使用控制台日志输出语句,我可以看到包装组件中的所有属性都被初始化,除了未定义的调度属性。我不明白为什么包装组件中未定义调度属性????

我正在使用 react-redux 7.1 并使用ConnectedPropsreact-redux 类型派生映射和调度属性。

高阶组件

import cuid from 'cuid';
import React, { Component, ComponentType } from 'react';

import { ConnectedProps } from 'react-redux';
import { RouteComponentProps, withRouter } from 'react-router-dom';

import { ApiErrorDialog } from './ApiErrorDialog';
import { ApiErrorListenerComponentProps } from './types';
import { connector } from './reduxConnect';

/**
 * Type declarations
 */
type HocState = {
  componentId: string;
};

type ReduxProps = ConnectedProps<typeof connector>;

export const withReduxErrorListener = <
  BaseProps extends ApiErrorListenerComponentProps
>(
  BaseComponent: ComponentType<BaseProps>,
) => {
  /**
   * Type declarations
   */
  type HocProps = BaseProps & ReduxProps & RouteComponentProps;
  type HocPropsExcludingBaseProps = Exclude<HocProps, BaseProps>;

  console.log(
    `withReduxErrorListener BaseProps => ${JSON.stringify(
      BaseComponent.displayName,
    )}`,
  );

  class ApiErrorListener extends Component<HocProps, HocState> {
    static displayName = `withReduxErrorListener(${BaseComponent.name})`;
    static readonly WrappedComponent = BaseComponent;
    /**
     * Some source code .....
     */


    render(): JSX.Element {
      const { ...restProps } = this.props;
      console.log('hoc render()');

      if (this.props.error.length > 0) {
        return (
          <React.Fragment>
            /*{display custom error component here}*/
          </React.Fragment>
        );
      } else {
        // display base component
        return (
          <BaseComponent componentId={this.state.componentId} {...restProps} />
        );
      }
    }
  }

  const ConnectedHoc = connector(ApiErrorListener as any);
  const RoutedConnectedHoc = withRouter(ConnectedHoc as any);
  return RoutedConnectedHoc;
};

包裹组件

type StateProps = {
  isLoading: boolean;
  courses: courseModels.Course[];
};

/**
 * Redux dispatch and state mappings
 */
const dispatchProps = {
  fetchCourses: apiCourseAction.request,
};

const mapStateToProps = (state: RootState): StateProps => ({
  isLoading: state.courses.isLoadingCourses,
  courses: courseSelectors.getReduxCourses(state.courses),
});

const connector = connect(
  mapStateToProps,
  dispatchProps,
);

type ReduxProps = ConnectedProps<typeof connector>;

/**
 * Component property type definitions
 */
type Props = ReduxProps & ApiErrorListenerComponentProps; // &RouteComponentProps;

/**
 * CourseList component
 */
const CourseListBase = ({
  courses = [],
  componentId,
  fetchCourses,
  isLoading,
}: Props): JSX.Element => {
  // dispatch fetch course action on mount
  useEffect(() => {
    console.log('My properties are:=> ');
    console.log(`courses :: ${JSON.stringify(courses)}`);
    console.log(`componentId :: ${componentId}`);
    console.log(`fetchCourses :: ${JSON.stringify(fetchCourses)}`);

    console.log('COURSELIST FETCHING COURSES');
    fetchCourses(requestFactories.getCourses(componentId));
  }, [fetchCourses]);

  if (isLoading) {
    return <p>Loading...</p>;
  }

  return (
    <div style={{ marginTop: 20, padding: 30 }}>
      {
        <Grid container spacing={2 as GridSpacing} justify="center">
          {courses.map(element => (
            <Grid item key={element.courseID}>
              <Course course={element} />
            </Grid>
          ))}
        </Grid>
      }
    </div>
  );
};

/**
 * Exports
 */

const ConnectedCourseList = connector(withReduxErrorListener(CourseListBase));
export default ConnectedCourseList;

更新于 26/11/2019 作为对评论的回应,我在这里创建了一个代码框。到目前为止,问题还没有体现在代码盒中,因此将在我的原始代码库中进一步调查。作为一个新的 react-redux 用户,任何关于我是否正确连接到代码和箱代码的高阶组件和基本组件中的 redux 存储的反馈,将不胜感激。

我也遇到了一个单独的问题,在代码沙箱的自述文件中有详细说明,我将为此提出一个单独的问题。

标签: typescriptreact-redux

解决方案


设法让它工作。该问题是由于错误地将 HoC 连接到 redux 存储,即组件被强制转换为任何。这个问题在一个单独的问题中得到解决。

重构 HoC 以遵循react-redux-typescript-guide中的嵌套 HOC 模式

感谢该指南的作者在确定解决方案方面付出的时间和耐心。感谢 downvoter 建议对问题进行最小限度的复制。

代码沙盒模型可以在这里找到


推荐阅读