Zrobiłem prosty <If />
komponent funkcji za pomocą 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;
}
Pozwala mi napisać czystszy kod, taki jak:
render() {
...
<If condition={truthy}>
presnet if truthy
</If>
...
W większości przypadków działa dobrze, ale gdy chcę na przykład sprawdzić, czy dana zmienna nie jest zdefiniowana, a następnie przekazać ją jako właściwość, staje się to problemem. Podam przykład:
Załóżmy, że mam komponent o nazwie, <Animal />
który ma następujące rekwizyty:
interface AnimalProps {
animal: Animal;
}
a teraz mam inny komponent, który renderuje następujący DOM:
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>
);
Jak skomentowałem, chociaż w rzeczywistości zwierzę nie jest zdefiniowane, nie mam sposobu, aby powiedzieć maszynopisowi, że już to sprawdziłem. Zapewnienie animal!
by działało, ale nie tego szukam.
Jakieś pomysły?
javascript
reactjs
typescript
Eliya Cohen
źródło
źródło
{animal !== undefined && <Anibal animal={animal} />}
zadziała<Animal animal={animal as Animal} />
Odpowiedzi:
To wydaje się niemożliwe.
Powód: jeśli zmienimy
If
komponentu zawartość zna odwrót
Dowiesz się, że tym razem chcesz, aby różnicowanie typów było przetwarzane w odwrotny sposób.
Co oznacza, że nie jest niezależny, co prowadzi do wniosku, że nie jest możliwe, aby taki typ różnił się w tym stanie, bez dotykania jednego z dwóch składników.
Nie jestem pewien, jakie jest najlepsze podejście, ale oto jedna z moich myśli.
Możesz zdefiniować
Animal component
rekwizytyanimal
za pomocątypów warunkowych Dystrybucyjnych maszynopisu : NonNullable .
Dokument
Stosowanie
Nie jest generowany przez
If
warunek komponentu, ale ponieważ używasz tylkochild component
tego warunku, sensowne jest zaprojektowaniechild component
rekwizytów jakonone nullable
, pod warunkiem, żeźródło
Krótka odpowiedź?
Nie możesz
Ponieważ zdefiniowałeś
animal
jakoAnimal | undefined
, jedynym sposobem na usunięcieundefined
jest utworzenie osłony lub przekształcenieanimal
jako czegoś innego. Masz ukryte strażnika wpisać stan nieruchomości oraz maszynopis nie ma możliwości dowiedzenia się, co się tam dzieje, więc nie może wiedzieć, że wybiera pomiędzyAnimal
iundefined
. Musisz go rzucić lub użyć!
.Zastanów się jednak: może to wydawać się czystsze, ale tworzy fragment kodu, który musi zostać zrozumiany i utrzymany, być może przez kogoś innego. W gruncie rzeczy tworzysz nowy język, złożony ze składników React, którego ktoś będzie musiał nauczyć się oprócz TypeScript.
Alternatywną metodą warunkowego wyprowadzenia JSX jest zdefiniowanie zmiennych,
render
które zawierają treść warunkową, takich jakJest to standardowe podejście, które inni programiści natychmiast rozpoznają i nie będą musieli szukać.
źródło
Korzystając z wywołania zwrotnego renderowania, jestem w stanie wpisać, że parametr return nie ma wartości null.
Nie jestem w stanie zmodyfikować twojego oryginalnego
If
komponentu, ponieważ nie wiem, co twojecondition
twierdzenia, a także jaką zmienną potwierdził, tjcondition={animal !== undefined || true}
Niestety stworzyłem nowy komponent
IsDefined
do obsługi tego przypadku:Wskazując, że
children
będzie to callback, który zostanie przekazany jako NonNullable typu T, który jest tego samego typu cocheck
.Dzięki temu otrzymamy wywołanie zwrotne renderowania, które zostanie przekazane do zmiennej o zerowej wartości.
Mam tutaj działający przykład https://codesandbox.io/s/blazing-pine-2t4sm
źródło
If
komponentu (żeby mógł wyglądać na czysty)