【问题标题】:How do i prevent circular type reference in typescript with redux and connect when using mapState function?如何在使用 mapState 函数时使用 redux 防止 typescript 中的循环类型引用和连接?
【发布时间】:2021-08-04 20:20:42
【问题描述】:

我一直在关注官方教程关于使用 redux 和 typescript here

一切正常,除非我需要在 mapState 中将传入的道具类型指定为 Props

这是我从打字稿中遇到的类型错误,我认为这意味着循环引用:

'connector' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.

以下是教程中的代码,除了 props: Props 添加到 mapState

import { connect, ConnectedProps } from 'react-redux';

interface RootState {
  isOn: boolean;
}

const mapState = (
  state: RootState,
  props: Props // <-- ERROR CAUSED BY ADDING TYPE 'Props' TO 'props'
) => ({
  isOn: state.isOn,
});

const mapDispatch = {
  toggleOn: () => ({ type: 'TOGGLE_IS_ON' }),
};

const connector = connect(mapState, mapDispatch);

// The inferred type will look like:
// {isOn: boolean, toggleOn: () => void}
type PropsFromRedux = ConnectedProps<typeof connector>;

interface Props extends PropsFromRedux {
  backgroundColor: string;
}

const MyComponent = (props: Props) => (
  <div style={{ backgroundColor: props.backgroundColor }}>
    <button onClick={props.toggleOn}>
      Toggle is {props.isOn ? 'ON' : 'OFF'}
    </button>
  </div>
);

export default connector(MyComponent);

我该如何解决这个问题?将类型从Props 设置为any 将丢失所有类型信息。任何帮助将非常感激。谢谢。

【问题讨论】:

  • 首先,这个问题应该解决吗?如果我正确理解您的代码,您基本上希望Props 拥有isOn 字段,即使它仅由mapState 提供。那么你期望mapState 获得当时不应该存在的isOn 字段的道具?
  • @KelvinSchoofs Props 期待 backgroundColor 字符串。 isOn 来自传递给 mapState 的 RootStatemapState 有两种参数类型,RootStateProps(来自原始组件的任何传入道具)。官方文件(非打字稿)允许这样做。传入这两个参数是有效的代码。
  • 仍然,您的Props 被定义为扩展PropsFromRedux,这就是循环依赖的来源。我的观点仍然成立:isOn 我认为。你的 Props 扩展了它被映射到的类型,这很可疑。
  • @KelvinSchoofs 您认为这样做的正确方法是什么?我需要将原始的 props 传递给 mapState 以获得额外的逻辑。
  • 你应该正确分割你的道具。一个清晰的接口用于传递给mapState,一个清晰的实例用于输出。

标签: reactjs typescript redux


【解决方案1】:

这里有一个正确的代码来处理这种情况:

import React from 'react'
import { connect, ConnectedProps } from 'react-redux';

interface RootState {
    isOn: boolean;
}

interface Props {
    backgroundColor: string;
}

const mapState = (
    state: RootState,
    props: Props
) => ({
    ...props, // <---- you should add own props here
    isOn: state.isOn,
});

const mapDispatch = {
    toggleOn: () => ({ type: 'TOGGLE_IS_ON' }),
};

const connector = connect(mapState, mapDispatch);

type PropsFromRedux = ConnectedProps<typeof connector>;

const MyComponent = (props: PropsFromRedux) => (
    <div style={{ backgroundColor: props.backgroundColor }}>
        <button onClick={props.toggleOn}>
            Toggle is {props.isOn ? 'ON' : 'OFF'}
        </button>
    </div>
);

const ConnectedComponent = connector(MyComponent)

const render = <ConnectedComponent backgroundColor="white" /> // ok

既然你已经将ownProps添加到mapState,你应该使用它。

Playground

【讨论】:

    猜你喜欢
    • 2021-02-05
    • 2019-01-03
    • 1970-01-01
    • 2014-08-18
    • 2019-07-24
    • 2021-09-13
    • 1970-01-01
    • 2021-03-12
    • 2015-02-19
    相关资源
    最近更新 更多