mapStateToProps OwnProps参数包含在高级组件

时间:2019-11-27 17:17:48

标签: reactjs typescript redux react-redux

我是新的react-redux用户,试图将更高阶的组件连接到react-redux存储。在将状态映射到props函数中,我正在使用ownProps参数来过滤状态。但是,我尝试在OwnProps中使用的属性始终未定义。有没有人经历过类似的事情?

Redux属性

import { connect } from "react-redux";

import { clearErrorAction } from "../features/errors/actions";
import { filterErrors } from "../features/errors/selectors";
import { FailureNotify } from "../features/errors/types";
import { HocComponentProps } from "./types";
import { RootState } from "typesafe-actions";

type StateProps = {
  error: FailureNotify[];
};

export const mapStateToProps = (
  state: RootState,
  ownProps: HocComponentProps
): StateProps => {
  // uniqueId property is always undefined here???
  console.log(`withErrorListener mapStateToProps => ${ownProps.uniqueId}`);
  return {
    error: filterErrors(state.errors as StateProps, ownProps)
  };
};

export const dispatchProps = {
  clearError: clearErrorAction
};

export const connector = connect(
  mapStateToProps,
  dispatchProps
);

高阶组件

import * as React from "react";

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

import { connector } from "./redux";
import { FailureNotify } from "../features/errors/types";

/**
 * Type declarations
 */
type ReduxProps = ConnectedProps<typeof connector>;
type ExpectedProps = { uniqueId: string };

/**
 * Internal components
 */
type ErrorInfoProps = { info: FailureNotify } & ReduxProps &
  RouteComponentProps;
const ErrorInfo = ({
  info,
  clearError,
  history
}: ErrorInfoProps): JSX.Element => {
  function goHome(): void {
    console.log("Go home button has been clicked");
    clearError(info.fromAction, info.fromComponent, history, "/");
  }
  return (
    <React.Fragment>
      <p>Error {info.message}</p>
      <p>Received from action {info.fromAction}</p>
      <p>Received for component id {info.fromComponent}</p>
      <button onClick={goHome}>Home</button>
    </React.Fragment>
  );
};

/**
 * HoC that renders errors on the redux store rasied for a component.
 * @param BaseComponent  The component to wrap should have uniqueId property
 */
export const withErrorListener = <BaseProps extends ExpectedProps>(
  BaseComponent: React.ComponentType<BaseProps>
) => {
  /**
   * Type declarations
   */
  type HocProps = BaseProps & ReduxProps & RouteComponentProps;

  class ErrorListener extends React.Component<HocProps, {}> {
    static displayName = `withErrorListener(${BaseComponent.name})`;
    static readonly WrappedComponent = BaseComponent;

    /**
     * Render error if there is one to display, otherwise render the base component
     * @returns Rendered error if error occurred. Rendered base component if no error occurred.
     */
    render() {
      const { ...restProps } = this.props;
      console.log(`withErrorListener [error_count=${this.props.error.length}]`);
      if (this.props.error.length > 0) {
        return <ErrorInfo info={this.props.error[0]} {...restProps} />;
      } else {
        return <BaseComponent {...restProps as BaseProps} />;
      }
    }
  }

  const ConnectedHoc = connector(ErrorListener as any);
  const RoutedHoc = withRouter(ConnectedHoc as any);

  return RoutedHoc;
};

Edit React Redux Typescript Nested Connected HoC  Example - AttemptingToSolve

我正在此source file

的末尾创建 withErrorListener 高阶组件的实例
const PostsListConnectedWithId = connector(withId(PostsListBase));
export const PostsListWithErrorListener = withErrorListener(
  PostsListConnectedWithId
);

PostsListBase 的源代码在同一source file

中可用

PostsListsWithErrorListener App组件中呈现。

始终未定义的属性是 uniqueId ,并由 withId 高阶组件here注入到基础组件中。 codeandbox内的控制台日志输出显示 uniqueId 属性值。

1 个答案:

答案 0 :(得分:0)

在问了另一个问题here之后,设法使它开始工作。

问题是混合错误地将HoC连接到Redux存储,即组件被强制转换为任意对象。此问题在单独的question中已解决。

其中一条评论建议uniqueId属性尚未初始化。我将withErrorListener HoC重构为注入uniqueId属性,以便无需开发人员就可以自动分配它。

可以找到密码和盒子模型here

如果评论者希望提出一个未初始化uniqueId属性的答案,那么我会接受。