redux 打字稿+React/还原:属性“XXX”在类型“IntrinsicAttributes和IntrinsicClassAttributes”上不存在

b09cbbtk  于 2022-11-12  发布在  React
关注(0)|答案(6)|浏览(176)

我在一个项目中使用了Typescript、React和Redux(都在Electron中运行),当我将一个基于类的组件包含在另一个组件中并试图在它们之间传递参数时,我遇到了一个问题。粗略地说,我得到了容器组件的以下结构:

class ContainerComponent extends React.Component<any,any> {
  ..
  render() {
    const { propToPass } = this.props;
    ...
    <ChildComponent propToPass={propToPass} />
    ...
  }
}

....
export default connect(mapStateToProps, mapDispatchToProps)(ContainerComponent);

和子组件:

interface IChildComponentProps extends React.Props<any> {
  propToPass: any
}

class ChildComponent extends React.Component<IChildComponentProps, any> {
  ...
}

....
export default connect(mapStateToProps, mapDispatchToProps)(ChildComponent);

很明显,我只包括了基本的内容,这两个类还有很多内容,但是当我尝试运行我认为是有效的代码时,仍然会出现错误。我得到的确切错误是:

TS2339: Property 'propToPass' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<{}, ComponentState>> & Readonly<{ childr...'.

当我第一次遇到这个错误时,我以为是因为我没有传入一个定义我的属性的接口,但是我创建了这个接口(正如你在上面看到的),它仍然不起作用。我想知道,是不是我遗漏了什么?
当我从ContainerComponent的代码中排除ChildComponent属性时,它会很好地呈现(除了我的ChildComponent没有关键属性之外),但是在JSX Typescript中却拒绝编译它。我认为这可能与基于this article的连接 Package 有关,但那篇文章中的问题发生在index.tsx文件中,是提供程序的问题。而我的问题在别处。

h6my8fg2

h6my8fg21#

因此,在阅读了一些相关的答案(特别是this onethis one,并查看了@basarat对该问题的答案)后,我设法找到了适合我的答案。(在我相对较新的React眼中)Connect似乎没有为容器组件提供显式接口,因此它被它试图传递的属性所迷惑。
因此,容器组件保持不变,但子组件发生了一些变化:

interface IChildComponentProps extends React.Props<any> {
  ... (other props needed by component)
}

interface PassedProps extends React.Props<any> {
  propToPass: any
}

class ChildComponent extends React.Component<IChildComponentProps & PassedProps, any> {
  ...
}

....
export default connect<{}, {}, PassedProps>(mapStateToProps, mapDispatchToProps)    (ChildComponent);

上面的方法对我来说是有效的。显式地传递组件期望从容器中得到的属性似乎是有效的,并且两个组件都正确地呈现了。

**注:**我知道这是一个非常简单的答案,我不知道为什么这工程,所以如果一个更有经验的React忍者想下降一些知识,这个答案,我很乐意修改它。

bvn4nwqk

bvn4nwqk2#

请仔细检查新添加的对象类型。如果对象类型与预期的不完全相同,则会引发此类错误。

**例如.**组件中提到的属性类型必须与传递给该组件的属性类型匹配。

a5g8bdjr

a5g8bdjr3#

使您的子组件扩展React.Component,使其具有您想要的类型或“任何”类型。例如:“extends React.Component<any> {...}

export class ChildComponent extends React.Component<T> {
 render() {
  return (
    <button className="square">
      {this.props.value}
    </button>
  );
 }
}

然后,您可以在父组件中传递值,例如:
renderSquare(i: Number) { return <ChildComponent value={i}/>; }
有关详细信息,请检查https://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/class_components/

vlurs2pr

vlurs2pr4#

在我的例子中,我构建了一个typescript组件,该组件导入了一个使用connect的javascript组件。
这里有一个快速的方法来修复这个错误。

// User is a javascript component
import _User from "./User";

// Inject types that this component accepts
const User = _User as unknown as React.JSXElementConstructor<{
 userId: string
}>;

const UserProfile = () => {
  const user = useCurrentUser();
  return (
    <div className="flex items-center justify-center">
      <User userId={user.userId} />
    </div>
  );
}

希望这对你有帮助!

cgfeq70w

cgfeq70w5#

对我有效的方法是将子组件类型从React.FC更改为JSX.Element
之前(警告)

const Component: React.FC = () => {

之后(无警告)

const Component = (): JSX.Element => {
bksxznpy

bksxznpy6#

请使用connect装饰器www.example.com代替export default connect(mapStateToProps, mapDispatchToProps)(ChildComponent);https://github.com/alm-tools/alm/blob/00f2f94efd3810af8a80a49f968c2ebdeb955399/src/app/fileTree.tsx#L136-L146

@connect((state: StoreState): Props => {
    return {
        filePaths: state.filePaths,
        filePathsCompleted: state.filePathsCompleted,
        rootDir: state.rootDir,
        activeProjectFilePathTruthTable: state.activeProjectFilePathTruthTable,
        fileTreeShown: state.fileTreeShown,
    };
})

此处定义连接的位置https://github.com/alm-tools/alm/blob/00f2f94efd3810af8a80a49f968c2ebdeb955399/src/typings/react-redux/react-redux.d.ts#L6-L36
为什么?
看起来你使用的定义可能已经过时或无效(也许是作者写得很差)。

相关问题