J'ai créé un <If />
composant fonctionnel simple en utilisant React:
import React, { ReactElement } from "react";
interface Props {
condition: boolean;
comment?: any;
}
export function If(props: React.PropsWithChildren<Props>): ReactElement | null {
if (props.condition) {
return <>{props.children}</>;
}
return null;
}
Cela me permet d'écrire un code plus propre, tel que:
render() {
...
<If condition={truthy}>
presnet if truthy
</If>
...
Dans la plupart des cas, cela fonctionne bien, mais lorsque je veux vérifier, par exemple, si une variable donnée n'est pas définie, puis la passer en tant que propriété, cela devient un problème. Je vais donner un exemple:
Disons que j'ai un composant appelé <Animal />
qui a les accessoires suivants:
interface AnimalProps {
animal: Animal;
}
et maintenant j'ai un autre composant qui rend le DOM suivant:
const animal: Animal | undefined = ...;
return (
<If condition={animal !== undefined} comment="if animal is defined, then present it">
<Animal animal={animal} /> // <-- Error! expected Animal, but got Animal | undefined
</If>
);
Comme je l'ai commenté, bien que l'animal ne soit pas défini, je n'ai aucun moyen de dire à Typescript que je l'ai déjà vérifié. L'affirmation de animal!
fonctionnerait, mais ce n'est pas ce que je recherche.
Des idées?
javascript
reactjs
typescript
Eliya Cohen
la source
la source
{animal !== undefined && <Anibal animal={animal} />}
- être que<Animal animal={animal as Animal} />
Réponses:
Cela semble impossible.
Raison: si nous changeons
If
le contenu du composant deà son opposé
Vous découvrirez que cette fois vous voulez que le type diff soit traité de la manière opposée.
Ce qui signifie qu'il n'est pas indépendant, ce qui conduit à la conclusion qu'il n'est pas possible de faire un tel type de différence dans cette condition, sans toucher à aucun des deux composants.
Je ne sais pas quelle est la meilleure approche, mais voici une de mes pensées.
Vous pouvez définir
Animal component
les accessoires deanimal
avec lestypes conditionnels distributifs du tapuscrit : NonNullable .
Document
Usage
Il n'est pas généré par la
If
condition du composant, mais comme vous n'utilisez que l'child component
intérieur de cette condition, il est logique de concevoir leschild component
accessoires de comme asnone nullable
sous la condition quela source
Réponse courte?
Tu ne peux pas.
Puisque vous avez défini
animal
commeAnimal | undefined
, la seule façon de supprimerundefined
est de créer un garde ou de refondreanimal
comme autre chose. Vous avez masqué la protection de type dans votre propriété condition et TypeScript n'a aucun moyen de savoir ce qui s'y passe, il ne peut donc pas savoir que vous choisissez entreAnimal
etundefined
. Vous devrez le lancer ou l'utiliser!
.Considérez, cependant: cela peut sembler plus propre, mais cela crée un morceau de code qui doit être compris et maintenu, peut-être par quelqu'un d'autre plus loin. En substance, vous créez un nouveau langage, composé de composants React, que quelqu'un devra apprendre en plus de TypeScript.
Une autre méthode de sortie conditionnelle de JSX consiste à définir des variables
render
qui contiennent votre contenu conditionnel, telles queIl s'agit d'une approche standard que les autres développeurs reconnaîtront instantanément et n'auront pas à rechercher.
la source
En utilisant un rappel de rendu, je peux taper que le paramètre de retour n'est pas nullable.
Je ne suis pas en mesure de modifier votre
If
composant d' origine car je ne sais pas ce que vouscondition
affirmez et quelle variable il a affirmé, c'est-à-direcondition={animal !== undefined || true}
Alors malheureusement, j'ai fait un nouveau composant
IsDefined
pour gérer ce cas:Indiquant que ce
children
sera un rappel, auquel sera transmis un NonNullable de type T qui est du même type quecheck
.Avec cela, nous aurons un rappel de rendu, auquel sera transmise une variable vérifiée par null.
J'ai un exemple de travail ici https://codesandbox.io/s/blazing-pine-2t4sm
la source
If
composant (afin qu'il puisse paraître propre)