Zacznijmy od nakreślenia przykładu, który wskaże nam istotne różnice. Stwórzmy identyczny wizualnie komponent, który będzie oparty na 2 wariantach.
/// pierwszy wariant
type HintCardProps = {
text: string;
children: React.ReactNode;
};
function HintCard({ text, children }: HintCardProps) {
return (
<div>
<p>{text}</p>
<div>{children}</div>
</div>
);
}
oraz
/// drugi wariant
type HintCardProps = {
text: string;
};
function HintCard({ text, children }: PropsWithChildren<HintCardProps>) {
return (
<div>
<p>{text}</p>
{children && <div>{children}</div>}
</div>
);
}
Kod w komponentach od razu wskazuje jakie różnice niesie za sobą każdy z wariantów. Tworząc komponent, który musi przekazać dodatkowe komponenty, stając się niejako wrapperem, lepiej jest posłużyć się propsem z ReactNode. Deklaracja typu PropsWithChildren tworzy typ pomocniczy z polem children jako opcjonalnym.
type PropsWithChildren<P = unknown> = P & { children?: ReactNode | undefined };
Różnica jest dość subtelna, lecz istotna. PropsWithChildren bierze właściwości komponentu (propsy) i zwraca przecięcie typu z właściwością children, zmniejszając boilerplate. Ważne jest, aby znać różnicę miedzy tymi 2 wariantami i świadomie z nich korzystać.
Powrót do artykułów