Typescript + React / Redux: la propriété «XXX» n'existe pas sur le type «IntrinsicAttributes & IntrinsicClassAttributes

91

Je travaille sur un projet avec Typescript, React et Redux (tous fonctionnant dans Electron), et j'ai rencontré un problème lorsque j'inclus un composant basé sur une classe dans un autre et que j'essaie de passer des paramètres entre eux. En gros, j'ai la structure suivante pour le composant conteneur:

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

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

Et le composant enfant:

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

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

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

Évidemment, je n'inclus que les bases et il y a beaucoup plus dans ces deux classes, mais j'obtiens toujours une erreur lorsque j'essaie d'exécuter ce qui me semble être du code valide. L'erreur exacte que j'obtiens:

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

Quand j'ai rencontré l'erreur pour la première fois, je pensais que c'était parce que je ne passais pas dans une interface définissant mes accessoires, mais j'ai créé cela (comme vous pouvez le voir ci-dessus) et cela ne fonctionne toujours pas. Je me demande, y a-t-il quelque chose qui me manque?

Quand j'exclus le prop ChildComponent du code dans le ContainerComponent, il rend très bien (mis à part le fait que mon ChildComponent n'a pas de prop critique) mais avec lui dans le JSX Typescript refuse de le compiler. Je pense que cela pourrait avoir quelque chose à voir avec le wrapping de connexion basé sur cet article , mais les problèmes dans cet article se sont produits dans le fichier index.tsx et étaient un problème avec le fournisseur, et je reçois mes problèmes ailleurs.

Protagoniste
la source

Réponses:

54

Donc, après avoir lu quelques réponses connexes (en particulier celle-ci et celle-ci et en regardant la réponse de @ basarat à la question, j'ai réussi à trouver quelque chose qui fonctionne pour moi. Il semble (à mes yeux React relativement nouveaux) comme Connect ne fournissait pas un interface explicite au composant conteneur, donc il a été confondu par le prop qu'il essayait de passer.

Ainsi, le composant conteneur est resté le même, mais le composant enfant a un peu changé:

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);

Ce qui précède a réussi à fonctionner pour moi. Passer explicitement les accessoires que le composant attend du conteneur semble fonctionner et les deux composants sont rendus correctement.

REMARQUE: je sais que c'est une réponse très simpliste et je ne sais pas exactement POURQUOI cela fonctionne, donc si un ninja React plus expérimenté veut abandonner certaines connaissances sur cette réponse, je serais heureux de la modifier.

Protagoniste
la source
7
Mais React.Propsa été obsolète !!
Sunil Sharma
-1

Au lieu de export default connect(mapStateToProps, mapDispatchToProps)(ChildComponent);, préférez le connectdécorateur 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,
    };
})

Où se connecter est défini ici https://github.com/alm-tools/alm/blob/00f2f94efd3810af8a80a49f968c2ebdeb955399/src/typings/react-redux/react-redux.d.ts#L6-L36

Pourquoi?

Il semble que les définitions que vous utilisez soient probablement obsolètes ou invalides (peut-être mal rédigées).

basarat
la source
2
Il semble que la connexion sur le composant enfant était définitivement le problème, mais j'ai trouvé un moyen de résoudre le problème sans changer les typages que j'utilisais. En utilisant la solution de ce lien, j'ai réussi à changer ma connexion à: connect<{}, {}, PassedProps> Where PassedProps est l'accessoire que le composant obtient de son conteneur parent.
Protagoniste