1.) Quelle est la différence entre JSX.Element, ReactNode et ReactElement ?
ReactElement et JSX.Element sont le résultat de l'invocation de React.createElement
directement ou via la transpilation JSX. Il s'agit d'un objet avec type
, props
y key
. JSX.Element
es ReactElement
dont props
y type
avoir le type any
Ils sont donc plus ou moins les mêmes.
const jsx = <div>hello</div>
const ele = React.createElement("div", null, "hello");
ReactNode est utilisé comme type de retour pour render()
dans les composants de la classe. C'est également le type par défaut pour children
avec l'attribut PropsWithChildren
.
const Comp: FunctionComponent = props => <div>{props.children}</div>
// children?: React.ReactNode
Cela semble plus compliqué dans le Déclarations de type React mais c'est équivalent à :
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...)
Vous pouvez attribuer presque tout à ReactNode
. Je préfère généralement des types plus forts, mais il peut y avoir des cas valables pour l'utiliser.
2.) Pourquoi les méthodes de rendu des composants de classe retournent-elles ReactNode, mais les composants de fonction retournent ReactElement ?
tl;dr : Il s'agit d'une incompatibilité de type TS actuelle non lié au noyau de React .
En principe, render()
dans les composants de classe React/JS supporte les mêmes types de retour en tant que composante de la fonction. En ce qui concerne les TS, les différents types sont une incohérence de type encore conservée pour des raisons historiques et le besoin de rétrocompatibilité.
Idéalement, un type de retour valide ressemblerait probablement plus à ça :
type ComponentReturnType = ReactElement | Array<ComponentReturnType> | string | number
| boolean | null // Note: undefined is invalid
3.) Comment puis-je résoudre ce problème par rapport à null ?
Quelques options :
// Use type inference; inferred return type is `JSX.Element | null`
const MyComp1 = ({ condition }: { condition: boolean }) =>
condition ? <div>Hello</div> : null
// Use explicit function return types; Add `null`, if needed
const MyComp2 = (): JSX.Element => <div>Hello</div>;
const MyComp3 = (): React.ReactElement => <div>Hello</div>;
// 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<MyProps> = () => <div>Hello</div>;
Note : Éviter le site React.FC
ne sauvera pas vous de la JSX.Element | null
restriction du type de retour.
Créer récemment une application React abandonné React.FC
à partir de son modèle, car il présente certaines particularités, comme l'utilisation implicite d'un {children?: ReactNode}
définition du type. Ainsi, en utilisant React.FC
avec parcimonie pourrait être préférable.
Dans les cas limites, vous pouvez ajouter une assertion de type ou des fragments comme solution de rechange :
const MyCompFragment: FunctionComponent = () => <>"Hello"</>
const MyCompCast: FunctionComponent = () => "Hello" as any
// alternative to `as any`: `as unknown as JSX.Element | null`