Definitelytyped: @types/react Possibilita renderizar uma string de um componente funcional

Criado em 13 out. 2017  ·  19Comentários  ·  Fonte: DefinitelyTyped/DefinitelyTyped

  • [x] Tentei usar o pacote @types/react e tive problemas.
  • [x] Tentei usar a versão estável mais recente do tsc. https://www.npmjs.com/package/typescript
  • [x] Tenho uma pergunta inadequada para StackOverflow . (Por favor, faça todas as perguntas apropriadas lá).
  • [x] [Mencione](https://github.com/blog/821-mention-somebody-they-re-notified) os autores (veja Definitions by: em index.d.ts ) para que eles possam responder.

    • Autores: @johnnyreilly , @bbenezech , ...

Com as tipagens atuais não é possível criar um componente sem estado que retorne uma string, número, booleano... (novo no React 16)

import React from 'react'

const TestString = () => {
    return 'Test String Component'
}

const Component = () => (
    <div>
        <TestString/>
    </div>
)

Erro que recebo:

JSX element type 'string' is not a constructor function for JSX elements.

O primeiro problema é que atualmente nas tipagens um componente sem estado não pode retornar nada além de uma instância de React.Element . Isso deve ser alterado para (acho que baseei nas alterações no método render , consulte https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react/index. d.ts#L422)

interface StatelessComponent<P = {}> {
        (props: P & { children?: ReactNode }, context?: any): ReactElement<any> | Array<ReactElement<any>> | string | number | null;
        propTypes?: ValidationMap<P>;
        contextTypes?: ValidationMap<any>;
        defaultProps?: Partial<P>;
        displayName?: string;
}

O segundo problema é que nos bastidores o compilador irá converter o jsx para `React.createElement('Test String Component', null)``

Eu recebo um erro do compilador que está dizendo que este não é um valor válido. Parece que deve ser um dos valores especificados na lista a seguir: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react/index.d.ts#L3465.

Alguma ideia de como isso pode ser corrigido?

Comentários muito úteis

Alguma novidade sobre este assunto?

Todos 19 comentários

@DovydasNavickas @sandersn @tkrotoff @andy-ms @ddwwcruz @apexskier @devrelm @RyanCavanaugh @richseviora @onigoetz @minestarks @yuit @sboehler @plantain-00 @p-jackson @miracle2k @voxmatt @morcerf @janechu @gaspard @vbfox @ericanderson @dyst5422 @rapilabs @cynecx @newyankeecodeshop

Provavelmente poderíamos definir componentes sem estado e baseados em classe como retornando ReactNode agora. Eu não migrei para a v16 sim, então isso precisaria de testes.

Parece que já tem um PR aberto. https://github.com/DefinitelyTyped/DefinitelyTyped/pull/20097

Isso está sendo trabalhado no caixa eletrônico?

Eu tentei alterá-lo, mas ele quebra o analisador JSX se o tipo de retorno for string boolean ou undefined .

Há um TypeScript PR em andamento sobre isso: https://github.com/Microsoft/TypeScript/pull/20239 (Bem, é sobre matrizes, mas geralmente é como o TS deve saber o que é permitido em um componente JSX)

Legal, obrigado pela atualização!

O que há de mais recente sobre isso? Vejo que o TS PR mencionado acima (https://github.com/Microsoft/TypeScript/pull/20239) agora está fechado/bloqueado. Eu me deparei com a mesma coisa hoje, novo em typescript + react, e me perguntando por que meus componentes não podem retornar strings de repente ...

Uma solução alternativa é retornar um fragmento.

return <>0</>

Alguma novidade sobre este assunto?

Olá, alguma atualização ou dicas sobre isso, por favor :) ?

Esta é essencialmente uma duplicata de # 18912. Depois que o Microsoft/TypeScript#21699 for resolvido, poderemos usar ReactNode como um tipo de retorno válido para componentes de função que incluem string e boolean .

Para generalizar o problema, por que deveria assumir o que é legítimo para o React? Com os pragmas @jsx / @jsxFrag Babel, uma abordagem como essa JSX pode funcionar com qualquer função. Portanto, não é que apenas strings devam ser admitidas; qualquer valor de retorno pode ser legítimo, limitado apenas pelo uso específico. React é importante, mas é apenas uma biblioteca de renderização específica.

Isso está aberto há quase dois anos, existe alguma solução?

Sobre o retorno sugerido de um fragmento <>StringValue vai aqui> - acho que estou tendo problemas para entender como obtenho o valor da string ou qualquer outro tipo de valor que não seja um React.Element realmente para usar no meu código - por exemplo, se Eu tenho uma função chamada Howdy retornando <>"hello"> e dentro de componentDidMount eu tenho

const o que diz =

como eu tiraria o valor da string do fragmento. Não estou vendo uma maneira, parece que qualquer maneira de contornar isso é um hack extremamente feio e considerando que a API Hooks é frequentemente usada para retornar apenas strings ou outros valores não React Element - por exemplo https://github. com/pankod/react-hooks-screen-type/blob/master/src/index.js
parece-me que esse bug realmente torna a API Hooks inutilizável e, como tal, torna o Typescript um ajuste ruim para o React.

Isso está aberto há quase dois anos, existe alguma solução?

@bryanrasmussen Consulte https://github.com/DefinitelyTyped/DefinitelyTyped/issues/20544#issuecomment -459665668 para obter a última atualização.

Esse problema está nos fazendo escrever um código React típico para contornar as limitações impostas pelo TypeScript. A única maneira de eliminar esses erros de uma maneira TypeScript é introduzir elementos DOM adicionais e/ou React.Fragments que adicionam sobrecarga (geram lixo) e não são necessários.

Isso nem sempre é um problema, pois surge de vez em quando e é acionado quando você retorna coisas válidas de componentes React que não são exatamente JSX.Element, por exemplo, um array.

Eu ficaria feliz com uma anotação de tipo sensata para ajudar as coisas, mas tenho que esmagá-las com coisas imperfeitas, como camadas adicionais e/ou any . Não é bom.

Embrulhar com um React.Fragment desnecessário tem um custo (insignificante) em tempo de execução.

Isso poderia ser outra solução sem penalidade de tempo de execução?

import React, { ReactElement } from 'react'

const TestString = () => {
  return ('Test String Component' as unknown) as ReactElement
}

const Component = () => (
  <div>
    <TestString />
  </div>
)

export default Component

Embrulhar com um React.Fragment desnecessário tem um custo (insignificante) em tempo de execução.

É um compromisso. Ainda assim, gostaria de ver melhor digitação para isso. Além disso, não insignificante, depende do contexto. Alguns fragmentos não doem, muitos sim.

Embrulhar com um React.Fragment desnecessário tem um custo (insignificante) em tempo de execução.

Isso poderia ser outra solução sem penalidade de tempo de execução?

import React, { ReactElement } from 'react'

const TestString = () => {
  return ('Test String Component' as unknown) as ReactElement
}

const Component = () => (
  <div>
    <TestString />
  </div>
)

export default Component

Sim, mas também perco a verificação de tipo para a função. Quero dizer, também posso remover o TS do meu projeto sem nenhuma penalidade de tempo de execução, mas não tenho verificação de tipo. Portanto, sua solução alternativa certamente está funcionando, mas apenas quebra o propósito do TS. Casting para "o que você espera" é como dizer "Ok, então vamos jogar fora as pausas. Quem precisa disso de qualquer maneira?". Quando você o envolve em um fragmento, obtém a verificação de tipo correta!

Então, alguma notícia sobre a correção?

Esta página foi útil?
0 / 5 - 0 avaliações