【问题标题】:React HOC TypeScript get rid of any type with Redux connectReact HOC TypeScript 使用 Redux connect 摆脱任何类型
【发布时间】:2020-08-21 15:33:07
【问题描述】:

总体思路是一个提供翻译能力的包装器组件。

顺便说一句,完整示例在这里 https://codesandbox.io/s/quizzical-hellman-v84ed 或 GitHub https://github.com/hitrov/translation-wrapper

这是 HOC 签名

export const wrapper = <P extends object>(Component: React.ComponentType<P>) =>
  (props: P & WithReplacementProps & IProps) => {...}

参数组件必须通过

interface WithReplacementProps {
  translatableProps: {
    getHeader(): string;
    getContent(): string;
  }
}

Redux 应该注入

interface IProps {
  language: string;

  setLanguage(language: string): SetLanguage;
}

这就是它的完成方式

type StateProps = Pick<IProps, | 'language'>;
type DispatchProps = Pick<IProps, | 'setLanguage'>;
type OwnProps = Omit<
  IProps,
  keyof StateProps | keyof DispatchProps
>;

const connector = connect<StateProps, DispatchProps, OwnProps, RootState>((state: RootState) => ({
  language: state.language,
}), {
  setLanguage,
});

问题是,当我尝试将 &lt;any&gt; 替换为允许安全检查类型的内容时,我总是遇到 TypeScript 错误。

export function withReplacement<T>(Component: React.ComponentType<T>) {
  return connector(wrapper<any>(Component));
}

这就是我如何使用包装组件

const ContentWithReplacement = withReplacement(Content);
...
<ContentWithReplacement
          key={header}
          header={header}
          content={content}
          translatableProps={{
            getContent: () => content,
            getHeader: () => header,
          }}
        />

内容组件很简单

export function Content(props: ContentProps) {
  const { translatedProps } = props;

  return (
    <>
      <h1>{translatedProps && translatedProps.header}</h1>
      <p>{translatedProps && translatedProps.content}</p>
    </>
  );
}

【问题讨论】:

  • import { ConnectedProps } from 'react-redux'; type PropsFromRedux = ConnectedProps&lt;typeof connector&gt;; 这对我也没有帮助

标签: reactjs redux react-redux higher-order-functions higher-order-components


【解决方案1】:

解决了这个问题。这对我帮助很大https://github.com/piotrwitek/react-redux-typescript-guide#--nested-hoc---wrapping-a-component-injecting-props-and-connecting-to-redux-

这就是我连接的 HOC 目前的样子

import React, { useReducer, useState } from "react";
import { reducer } from "../reducers";
import { Select } from "../Select";
import { connect } from 'react-redux';
import { RootState } from "../reducers/redux";
import { setLanguage, SetLanguage, } from '../reducers/language';
import { Diff } from 'utility-types';

interface InjectedProps {
  language: string;

  setLanguage(language: string): SetLanguage;
}

interface WithReplacementProps {
  translatableProps: {
    getHeader(): string;
    getContent(): string;
  }
}

export const withReplacement = <BaseProps extends {}>
(Component: React.ComponentType<BaseProps>) => {

  const mapStateToProps = (state: RootState) => ({
    language: state.language,
  });

  const dispatchProps = {
    setLanguage: (language: string) => setLanguage(language),
  };

  type PropsFromRedux = ReturnType<typeof mapStateToProps> &
    typeof dispatchProps & {
    // here you can extend ConnectedHoc with new props
    // overrideCount?: number;
  };

  const Hoc = (props: PropsFromRedux & WithReplacementProps) => {

    const { translatableProps, language, setLanguage, ...rest } = props;

    const [ showOriginal, setShowOriginal ] = useState(true);

    const { getHeader, getContent } = translatableProps;
    let header = getHeader();
    let content = getContent();

    const [ state, dispatch ] = useReducer(reducer, {...);

    return (
      <>
        <Component
          {...rest as BaseProps}
          translatedProps={{
            header,
            content,
          }}
        />
        <Select
          language={language}
          onChange={e => {
            setLanguage(e.target.value);
          }}
        />
      </>
    );
  };

  return connect<ReturnType<typeof mapStateToProps>,
    typeof dispatchProps, // use "undefined" if NOT using dispatchProps
    Diff<BaseProps, InjectedProps>,
    RootState>(
    mapStateToProps,
    dispatchProps
  )(Hoc);
};

【讨论】:

    猜你喜欢
    • 2019-03-07
    • 2019-01-22
    • 2016-06-13
    • 2023-04-03
    • 2019-11-28
    • 1970-01-01
    • 2021-03-19
    • 1970-01-01
    • 2021-10-27
    相关资源
    最近更新 更多