Definitelytyped: @types/react Hacer posible renderizar una cadena desde un componente funcional

Creado en 13 oct. 2017  ·  19Comentarios  ·  Fuente: DefinitelyTyped/DefinitelyTyped

  • [x] Intenté usar el paquete @types/react y tuve problemas.
  • [x] Intenté usar la última versión estable de tsc. https://www.npmjs.com/package/mecanografiado
  • [x] Tengo una pregunta que no es apropiada para StackOverflow . (Por favor haga las preguntas apropiadas allí).
  • [x] [Mencionar](https://github.com/blog/821-mention-somebody-they-re-notified) a los autores (ver Definitions by: en index.d.ts ) para que puedan responder.

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

Con los tipos actuales, no es posible crear un componente sin estado que devuelva una cadena, un número, un valor booleano... (nuevo en React 16)

import React from 'react'

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

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

error me sale:

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

El primer problema es que actualmente en las tipificaciones, un componente sin estado no puede devolver nada más que una instancia de React.Element . Esto debería cambiarse a (creo que me basé en los cambios en el 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;
}

El segundo problema es que detrás de escena el compilador convertirá el jsx a `React.createElement('Test String Component', null)``

Recibo un error del compilador que dice que este no es un valor válido. Parece que tiene que ser uno de los valores especificados en la siguiente lista: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react/index.d.ts#L3465.

¿Alguna idea sobre cómo se puede solucionar esto?

Comentario más útil

¿Alguna novedad sobre este asunto?

Todos 19 comentarios

@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

Probablemente podríamos definir los componentes sin estado y basados ​​en clases como que devuelven ReactNode ahora. No he migrado a v16, sí, por lo que necesitaría pruebas.

Parece que ya hay un PR abierto. https://github.com/DefinitelyTyped/DefinitelyTyped/pull/20097

¿Esto se está trabajando en cajero automático?

Intenté cambiarlo, pero rompe el analizador JSX si el tipo de retorno es string boolean o undefined .

Hay un PR de TypeScript en progreso al respecto: https://github.com/Microsoft/TypeScript/pull/20239 (Bueno, se trata de matrices, pero generalmente es cómo TS debe saber qué está permitido en un componente JSX)

Genial, gracias por la actualización!

¿Qué es lo último sobre esto? Veo que el TS PR mencionado anteriormente (https://github.com/Microsoft/TypeScript/pull/20239) ahora está cerrado/bloqueado. Me encontré con lo mismo hoy, nuevo en mecanografiar + reaccionar, y me preguntaba por qué mis componentes no pueden devolver cadenas de repente...

Una solución consiste en devolver un fragmento.

return <>0</>

¿Alguna novedad sobre este asunto?

Hola, ¿alguna actualización o sugerencia sobre esto, por favor :)?

Esto es esencialmente un duplicado de #18912. Una vez que se resuelva Microsoft/TypeScript#21699, deberíamos poder usar ReactNode como un tipo de retorno válido para los componentes de funciones que incluyen string y boolean .

Para generalizar el problema, ¿por qué debería asumir lo que es legítimo para React? Con los pragmas de Babel @jsx / @jsxFrag , un enfoque como este JSX puede funcionar con cualquier función. Entonces ni siquiera es que solo se deban admitir cadenas; cualquier valor de retorno puede ser legítimo, limitado solo por el uso específico. React es importante, pero es solo una biblioteca de renderizado específica.

Esto ha estado abierto durante casi un par de años, ¿hay alguna solución?

Acerca de la devolución sugerida de un fragmento <>StringValue va aquí> - Supongo que tengo problemas para entender cómo obtengo el valor de la cadena, o cualquier otro tipo de valor que no sea un React.Element realmente para usar en mi código, por ejemplo si Tengo una función llamada Howdy que regresa <>"hello"> y dentro del componenteDidMount tengo

constante lo que dice =

¿Cómo obtendría el valor de la cadena del fragmento? No veo una manera, parece que cualquier forma de evitar esto es un truco extremadamente feo y teniendo en cuenta que la API de Hooks se usa a menudo para devolver solo cadenas u otros valores que no son de React Element, por ejemplo, https://github. com/pankod/react-hooks-screen-type/blob/master/src/index.js
Me parece que este error realmente hace que la API de Hooks sea inutilizable y, como tal, hace que Typescript no se ajuste bien a React.

Esto ha estado abierto durante casi un par de años, ¿hay alguna solución?

@bryanrasmussen Consulte https://github.com/DefinitelyTyped/DefinitelyTyped/issues/20544#issuecomment -459665668 para obtener la última actualización.

Este problema nos hace escribir un código React atípico para evitar las limitaciones impuestas por TypeScript. La única forma de aplastar estos errores de forma mecanografiada es introducir elementos DOM adicionales y/o React.Fragments que agregan sobrecarga (generan basura) y no son necesarios.

Esto no siempre es un problema, ya que surge de vez en cuando y se activa cuando devuelve cosas válidas de los componentes de React que no son exactamente JSX.Element, por ejemplo, una matriz.

Estaría feliz con una anotación de tipo sensata para ayudar a las cosas, pero tengo que aplastarlas con cosas imperfectas como capas adicionales y/o any . No es bueno.

Envolver con un React.Fragment innecesario tiene un costo (insignificante) en tiempo de ejecución.

¿Podría ser esta otra solución sin penalización de tiempo de ejecución?

import React, { ReactElement } from 'react'

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

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

export default Component

Envolver con un React.Fragment innecesario tiene un costo (insignificante) en tiempo de ejecución.

Es un compromiso. Aún así, me gustaría ver una mejor escritura para esto. Además, no sin importancia, depende del contexto. Unos pocos fragmentos no duelen, muchos de ellos lo harán.

Envolver con un React.Fragment innecesario tiene un costo (insignificante) en tiempo de ejecución.

¿Podría ser esta otra solución sin penalización de tiempo de ejecución?

import React, { ReactElement } from 'react'

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

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

export default Component

Sí, pero luego también pierdo el tipo de verificación de la función. Quiero decir que también puedo eliminar TS de mi proyecto sin ninguna penalización de tiempo de ejecución, pero no tengo verificación de tipo. Entonces, su solución seguramente funciona, pero solo rompe el propósito de TS. Enviar a "lo que esperas" es como decir "Está bien, entonces desechemos los descansos. ¿Quién necesita esto de todos modos?". Cuando lo envuelve en un fragmento, ¡obtiene la verificación de tipo correcta!

Entonces, ¿alguna noticia sobre la corrección?

¿Fue útil esta página
0 / 5 - 0 calificaciones