Investigamos por distintos espacios y así darte la solución a tu dilema, si continúas con alguna duda déjanos la pregunta y te contestamos porque estamos para ayudarte.
Solución:
¿Cuál es la diferencia entre JSX.Element, ReactNode y ReactElement?
Un ReactElement es un objeto con un tipo y accesorios.
type Key = string | number
interface ReactElement = string | JSXElementConstructor> null;
Un ReactNode es un ReactElement, un ReactFragment, un stringun número o un array de ReactNodes, o nullo indefinido, o un booleano:
type ReactText = string | number;
type ReactChild = ReactElement | ReactText;
interface ReactNodeArray extends Array
type ReactFragment = | ReactNodeArray;
type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;
JSX.Element es un ReactElement, con el tipo genérico para accesorios y el tipo es cualquiera. Existe, ya que varias bibliotecas pueden implementar JSX a su manera, por lo tanto, JSX es un espacio de nombres global que luego establece la biblioteca, React lo establece así:
declare global
namespace JSX
interface Element extends React.ReactElement
Por ejemplo:
// <- ReactElement = JSX.Element
// <- ReactElement = JSX.Element
true && "test" // <- ReactNode
¿Por qué los métodos de representación de los componentes de clase devuelven ReactNode, pero los componentes de función devuelven ReactElement?
De hecho, devuelven cosas diferentes. Component
s retorno:
render(): ReactNode;
Y las funciones son “componentes sin estado”:
interface StatelessComponent null;
// ... doesn't matter
En realidad, esto se debe a razones históricas.
¿Cómo soluciono esto con respecto a null?
Escríbelo como ReactElement | null
tal como reacciona. O deje que Typescript infiera el tipo.
fuente de los tipos
1.) ¿Cuál es la diferencia entre JSX.Element, ReactNode y ReactElement?
ReactElement y JSX.Element
son el resultado de invocar React.createElement
directamente o a través de la transpilación JSX. es un objeto con type
, props
y key
. JSX.Element
es ReactElement
cuyo props
y type
tener tipo any
por lo que son más o menos lo mismo.
const jsx = hello
const ele = React.createElement("div", null, "hello");
ReactNode se utiliza como tipo de retorno para render()
en componentes de clase. También es el tipo predeterminado para children
attribute con PropsWithChildren
.
const Comp: FunctionComponent = props => props.children
// children?: React.ReactNode
Parece más complicado en las declaraciones de tipo React, pero es equivalente para:
type ReactNode = | null | undefined;
// super type `` has absorbed *all* other types, which are sub types of ``
// so it is a very "broad" type (I don't want to say useless...)
Puede asignar casi todo a ReactNode
. Por lo general, preferiría tipos más fuertes, pero podría haber algunos casos válidos para usarlo.
2.) ¿Por qué los métodos de representación de los componentes de clase devuelven ReactNode, pero los componentes de función devuelven ReactElement?
tl; dr: Es una incompatibilidad de tipo TS actual que no está relacionada con el núcleo de React.
-
Componente de clase TS: devoluciones
ReactNode
conrender()
más permisivo que React/JS -
Componente de la función TS: devoluciones
JSX.Element | null
más restrictivo que React/JS
En principio, render()
en los componentes de clase React/JS admite los mismos tipos de devolución que un componente de función. Con respecto a TS, los diferentes tipos son una inconsistencia de tipos que aún se mantiene debido a razones históricas y la necesidad de compatibilidad con versiones anteriores.
Idealmente, un tipo de retorno válido probablemente se parecería más a esto:
type ComponentReturnType = ReactElement | Array | string | number
| boolean | null // Note: undefined is invalid
3.) ¿Cómo resuelvo esto con respecto a null?
Algunas opciones:
// Use type inference; inferred return type is `JSX.Element | null`
const MyComp1 = ( condition : condition: boolean ) =>
condition ? Hello : null
// Use explicit function return types; Add `null`, if needed
const MyComp2 = (): JSX.Element => Hello;
const MyComp3 = (): React.ReactElement => Hello;
// Option 3 is equivalent to 2 + we don't need to use a global (JSX namespace)
// Use built-in `FunctionComponent` or `FC` type
const MyComp4: React.FC = () => Hello;
Nota: Evitando React.FC
no te salvará de la JSX.Element | null
restricción de tipo de retorno.
Crear aplicación React lanzada recientemente React.FC
de su plantilla, ya que tiene algunas peculiaridades como un implícito children?: ReactNode
definición de tipo. entonces usando React.FC
con moderación podría ser preferible.
En casos extremos, puede agregar una aserción de tipo o Fragmentos como solución alternativa:
const MyCompFragment: FunctionComponent = () => <>"Hello">
const MyCompCast: FunctionComponent = () => "Hello" as any
// alternative to `as any`: `as unknown as JSX.Element | null`
Eres capaz de añadir valor a nuestro contenido contribuyendo tu experiencia en las crónicas.