Typescript + React / Redux: A propriedade “XXX” não existe no tipo 'IntrinsicAttributes & IntrinsicClassAttributes

96

Estou trabalhando em um projeto com Typescript, React e Redux (todos rodando em Electron), e tive um problema ao incluir um componente baseado em classe em outro e tentar passar parâmetros entre eles. Em termos gerais, tenho a seguinte estrutura para o componente do contêiner:

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

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

E o componente filho:

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

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

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

Obviamente, estou incluindo apenas o básico e há muito mais nessas duas classes, mas ainda recebo um erro quando tento executar o que me parece um código válido. O erro exato que estou recebendo:

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

Quando encontrei o erro pela primeira vez, pensei que era porque não estava passando uma interface definindo meus adereços, mas eu criei isso (como você pode ver acima) e ainda não funciona. Estou pensando, há algo que estou perdendo?

Quando excluo o prop ChildComponent do código no ContainerComponent, ele renderiza muito bem (além de meu ChildComponent não ter um prop crítico), mas com ele no JSX Typescript se recusa a compilá-lo. Acho que pode ter algo a ver com o agrupamento de conexão com base neste artigo , mas os problemas naquele artigo ocorreram no arquivo index.tsx e eram um problema com o provedor, e estou obtendo meus problemas em outro lugar.

Protagonista
fonte

Respostas:

56

Depois de ler algumas respostas relacionadas (especificamente esta e esta e observar a resposta de @bassarat à pergunta, consegui encontrar algo que funciona para mim. Parece (para meus olhos relativamente novos do React) que o Connect não estava fornecendo um interface explícita para o componente do contêiner, então ele foi confundido pelo prop que estava tentando passar.

Portanto, o componente do contêiner permaneceu o mesmo, mas o componente filho mudou um pouco:

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

O acima conseguiu funcionar para mim. Passar explicitamente os adereços que o componente espera do contêiner pareceu funcionar e ambos os componentes renderizados corretamente.

NOTA: Eu sei que esta é uma resposta muito simplista e não tenho certeza de POR QUE isso funciona, então se um ninja React mais experiente quiser se aprofundar nessa resposta, eu ficaria feliz em alterá-la.

Protagonista
fonte
7
Mas React.Propsfoi descontinuado !!
Sunil Sharma
1
medium.com/knerd/…
hytromo de
0

Verifique os tipos de objeto recém-adicionados. Quando o tipo de objeto não é exatamente o esperado, esse erro é gerado.

Ex. O tipo de adereços mencionados no componente deve corresponder ao tipo de adereços que são passados ​​para aquele componente.

Yuvraj Patil
fonte
-2

Em vez de export default connect(mapStateToProps, mapDispatchToProps)(ChildComponent);, prefira o connectdecorador 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,
    };
})

Onde a conexão é definida aqui https://github.com/alm-tools/alm/blob/00f2f94efd3810af8a80a49f968c2ebdeb955399/src/typings/react-redux/react-redux.d.ts#L6-L36

Por quê?

Parece que as definições que você está usando provavelmente estão desatualizadas ou inválidas (talvez com uma redação incorreta).

Basarat
fonte
3
Parece que conectar no componente filho era definitivamente o problema, mas encontrei uma maneira de resolver o problema sem alterar as digitações que estava usando. Usando a solução neste link , consegui mudar minha conexão para: connect<{}, {}, PassedProps> Onde PassedProps é o suporte que o componente obtém de seu contêiner pai.
Protagonista