Tengo un componente funcional muy simple de la siguiente manera:
import * as React from 'react';
export interface AuxProps {
children: React.ReactNode
}
const aux = (props: AuxProps) => props.children;
export default aux;
Y otro componente:
import * as React from "react";
export interface LayoutProps {
children: React.ReactNode
}
const layout = (props: LayoutProps) => (
<Aux>
<div>Toolbar, SideDrawer, Backdrop</div>
<main>
{props.children}
</main>
<Aux/>
);
export default layout;
Sigo recibiendo el siguiente error:
[ts] El tipo de elemento JSX 'ReactNode' no es una función de constructor para elementos JSX. El tipo 'indefinido' no se puede asignar al tipo 'ElementClass'. [2605]
¿Cómo escribo esto correctamente?
reactjs
typescript
jsx
typescript2.0
Asool
fuente
fuente
JSX.Element
no es lo suficientemente bueno ya que un niño React válido podría ser una cadena, un booleano, nulo ... tambiénReactChild
está incompleto por las mismas razonesReactNode
. No ayuda en términos de seguridad de tipos, similar a escribirchildren
comoany
: vea mi respuesta para obtener una explicación.Para usarlo
<Aux>
en su JSX, debe ser una función que regreseReactElement<any> | null
. Esa es la definición de un componente de función. .Sin embargo, actualmente se define como una función que devuelve
React.ReactNode
, que es un tipo mucho más amplio. Como dicen los mecanografiados de React:Asegúrese de que los tipos no deseados se neutralicen envolviendo el valor devuelto en React Fragment (
<></>
):fuente
children
en un fragmento de reacción. ¿Le importaria explicar? En React es perfectamente válido soloreturn children;
.children
son una matriz. Si ese es el caso, debe envolverlos en un solo nodo o usar React Fragments.return React.Children.count(children) > 1 ? <>{children}</> : children
pero mecanografiado se queja de eso. Lo reemplacé con solo<>{children}</>
.children
es una lista de elementos que contiene solo 1 elemento. Creo que funcionaría si loreturn React.Children.count(children) > 1 ? <>{children}</> : children[0]
hicieras @sanfilippopablo<React.Fragment>
alrededores{props.children}
no devuelvo nada.Esto es lo que funcionó para mí:
Editar , recomendaría usar en su
children: React.ReactNode
lugar ahora.fuente
<MyComponent>{ condition ? <span>test</span> : null}</MyComponent>
. El usochildren: ReactNode
funcionará.puedes declarar tu componente así:
fuente
Puede utilizar
ReactChildren
yReactChild
:fuente
Desde el sitio de TypeScript: https://github.com/Microsoft/TypeScript/issues/6471
Eso funcionó para mí. El nodo hijo puede tener muchas cosas diferentes, por lo que la escritura explícita puede omitir casos.
Hay una discusión más larga sobre el problema de seguimiento aquí: https://github.com/Microsoft/TypeScript/issues/13618 , pero el enfoque any todavía funciona.
fuente
El tipo de retorno del componente de función está limitado a
JSXElement | null
TypeScript. Esta es una limitación de tipo actual, React puro permite más tipos de retorno.Fragmento de demostración mínimo
Puede usar una aserción de tipo o Fragmentos como solución alternativa:
ReactNode
children: React.ReactNode
puede ser subóptimo, si el objetivo es tener tipos fuertes paraAux
.Casi todo se puede asignar al
ReactNode
tipo actual , que es equivalente a{} | undefined | null
. Un tipo más seguro para su caso podría ser:Ejemplo:
Dadas las
Aux
necesidades de los elementos de React comochildren
, accidentalmente le agregamos unstring
. Entonces la solución anterior sería un error en contraste conReactNode
: eche un vistazo a los patios de recreo vinculados.Typed
children
también es útil para accesorios que no son JSX, como una devolución de llamada de Render Prop .fuente
También puede utilizar
React.PropsWithChildren<P>
.fuente
La forma general de encontrar cualquier tipo es mediante un ejemplo. La belleza del mecanografiado es que tiene acceso a todos los tipos, siempre que tenga los
@types/
archivos correctos .Para responder a esto yo mismo, solo pensé en un componente que usa react que tiene el
children
prop. ¿Lo primero que le vino a la mente? ¿Qué tal un<div />
?Todo lo que necesita hacer es abrir vscode y crear un nuevo
.tsx
archivo en un proyecto de reacción con@types/react
.Al pasar el cursor sobre el
children
accesorio, se muestra el tipo. ¿Y qué sabes? Su tipo esReactNode
(no es necesarioReactNode[]
).Luego, si hace clic en la definición de tipo, lo lleva directamente a la definición de interfaz
children
provenienteDOMAttributes
.fuente
Como tipo que contiene niños, estoy usando:
Este tipo de contenedor para niños es lo suficientemente genérico para admitir todos los casos diferentes y también está alineado con la API de ReactJS.
Entonces, para su ejemplo, sería algo como:
fuente
Estas respuestas parecen estar desactualizadas: React ahora tiene un tipo integrado
PropsWithChildren<{}>
. Se define de manera similar a algunas de las respuestas correctas en esta página:type PropsWithChildren<P> = P & { children?: ReactNode };
fuente
P
en el caso de ese tipo?P
es el tipo de accesorios de su componenteLos componentes de React deben tener un solo nodo contenedor o devolver una matriz de nodos.
Su
<Aux>...</Aux>
componente tiene dos nodosdiv
ymain
.Trate de envolver a sus hijos en una
div
deAux
componente.fuente