创建可重用的 Redux 连接器(具有相同的 mapState 和 mapDispatch) - 存在 TypeScript 问题

Posted

技术标签:

【中文标题】创建可重用的 Redux 连接器(具有相同的 mapState 和 mapDispatch) - 存在 TypeScript 问题【英文标题】:Create reusable Redux connector (with the same mapState and mapDispatch) - having TypeScript issues 【发布时间】:2020-12-11 12:29:57 【问题描述】:

这里的组件可以选择呈现字符串(未连接到 Redux 存储)或选择框。

export function Content(props: ContentProps) 
  const  language  = props;

  if (!props.setLanguage) 
    return (
      <div>language</div>
    );
  

  return (
    <Select
      language=language
      languages=languages
      onChange=e => 
        props.setLanguage!(e.target.value);
      
    />
  );

这段代码运行良好

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

const mapDispatch = 
  setLanguage,
;

const connector = connect(mapStateToProps, mapDispatch);

const ConnectedContent = connector(Content);

function App() 
  return (
    <ConnectedContent />
  );

但问题是我需要额外的增强功能,所以连接器必须是可重复使用的,比如

//type PropsFromRedux = ConnectedProps<typeof connector>;

interface LoadingProps 
  loading?: boolean;


const withLoading = <P extends >(Component: React.ComponentType<P>) => (props: P & LoadingProps) => (
  <>
    props.loading && <div>Loading</div>
    <Component ...props as P />
  </>
);

function getConnectedComponent(Component: React.ComponentType) 
  const ComponentWithLoading = withLoading(Component);

  return connector(ComponentWithLoading);


const ConnectedContent = getConnectedComponent(Content);

但我不知道如何正确地将类型/泛型添加到 getConnectedComponent 函数中。通过推断,我得到了

Error:(24, 48) TS2345: Argument of type '(props: ContentProps) => Element' is not assignable to parameter of type 'ComponentType<>'.
  Type '(props: ContentProps) => Element' is not assignable to type 'FunctionComponent<>'.
    Types of parameters 'props' and 'props' are incompatible.
      Property 'language' is missing in type ' children?: ReactNode; ' but required in type 'ContentProps'.

工作示例位于https://codesandbox.io/s/elegant-snowflake-b5r89 也推送到 GitHub https://github.com/hitrov/reusable-redux-connector

【问题讨论】:

【参考方案1】:

我不确定您所说的“连接器应该是可重复使用的”是什么意思,或者您所指的“附加增强功能”是什么意思。 已经可以重复使用了。从connect(mapState, mapDispatch) 返回的函数已准备好接受您传入的任何组件,因此它已经执行了您名义上的getConnectedComponent 想要执行的操作。

【讨论】:

您好,感谢您的回复,是的,如果我导出此连接器变量 - 它会。但是想象一下,在将组件传递给连接器之前,我需要对组件进行额外的增强(例如,将 HOC 应用到它)——这就是为什么我必须有一个函数来接收组件作为参数,然后将连接器应用到它 不,不需要“增强”,我不知道你从哪里得到这个想法。任何组件都可以传递给connector() 函数,它会工作。期间。 你告诉我我不需要,而我这样做=)我已经添加了上面的示例 - 假设我需要在传递给连接器之前或之后应用 withLoading HOC。有没有其他方法可以做到这一点? withLoading HOC 的使用特定于您自己的应用程序。我的观点是,就 React-Redux 而言,为了成功调用 const ConnectedComponent = connector(MyComponent),不需要做任何其他事情。在这一点上,我不知道实际的问题是什么,tbh。

以上是关于创建可重用的 Redux 连接器(具有相同的 mapState 和 mapDispatch) - 存在 TypeScript 问题的主要内容,如果未能解决你的问题,请参考以下文章

Redux:重用reducer来更新多个状态属性

此类中的数据库连接是不是“可重用”?

具有连接的实体和存储库中的教义可重用标准

在组件外部使用 redux 钩子来实现代码的可重用性

是否可以为 useSelector 创建一个可重用的函数?

在 Redux Saga 中重用 websocket 连接对象