javascript - TypeScript React.FC<Props> karışıklığı
TypeScript öğreniyorum ve bazı kısımlar benim için kafa karıştırıcı. Bir kısım aşağıda:
interface Props {
name: string;
}
const PrintName: React.FC<Props> = (props) => {
return (
<div>
<p style={{ fontWeight: props.priority ? "bold" : "normal" }}>
{props.name}
</p>
</div>
)
}
const PrintName2 = (props: Props) => {
return (
<div>
<p style={{ fontWeight: props.priority ? "bold" : "normal" }}>
{props.name}
</p>
</div>
)
}
Yukarıdaki her iki fonksiyonel bileşen için de, TypeScript'in aynı JS kodunu ürettiğini görüyorum. PrintName2 bileşeni bana okunabilirlik açısından daha sade görünüyor. İki tanım arasındaki farkın ne olduğunu ve birinin ikinci tür React bileşenini kullanıp kullanmadığını merak ediyorum.
Cevap #1
Herkese cevaplar için teşekkürler. Doğru ama ben daha detaylı bir sürüm arıyordum. Biraz daha araştırma yaptım ve GitHub'daki React+TypeScript Hile Sayfalarında bunu buldum.
Fonksiyon Bileşenleri
Bunlar, bir props argümanı alan ve bir JSX öğesi döndüren normal fonksiyonlar olarak yazılabilir.
type AppProps = { message: string }; /* could also use interface */
const App = ({ message }: AppProps) => <div>{message}</div>;
React.FC/React.FunctionComponent hakkında ne düşünüyorsunuz? Bileşenleri ayrıca React.FunctionComponent (veya kısaca React.FC) ile de yazabilirsiniz:
const App: React.FC<{ message: string }> = ({ message }) => (
<div>{message}</div>
);
“Normal fonksiyon” versiyonundan bazı farklar:
Statik özellikler için displayName, propTypes ve defaultProps gibi tip kontrolü ve otomatik tamamlama sağlar - Ancak, şu anda React.FunctionComponent ile defaultProps kullanımıyla ilgili bilinen sorunlar vardır. Ayrıntılar için bu soruna bakın - tip önerileri için aşağı kaydırarak defaultProps bölümümüze bakın.
Bu, çocukların örtük bir tanımını sağlar (aşağıya bakınız) - ancak örtük children türü ile bazı sorunlar vardır (ör. DefinitelyTyped#33006) ve yine de children'ı kullanan bileşenler konusunda açık olmak daha iyi bir stil olarak düşünülebilir.
const Title: React.FunctionComponent<{ title: string }> = ({
children,
title
}) => <div title={title}>{children}</div>;
Gelecekte, props otomatik olarak salt okunur olarak işaretlenebilir, ancak props nesnesi parametre listesinde dağıtılmışsa bu önemsiz bir noktadır.
React.FunctionComponent dönüş türü hakkında açıktır, oysa normal fonksiyon sürümü örtük (veya ek açıklama gerektirir).
Çoğu durumda hangi sözdiziminin kullanıldığı çok az fark yaratır, ancak
React.FCsözdizimi net bir avantaj sağlamadan biraz daha ayrıntılıdır, bu nedenle öncelik "normal fonksiyon" sözdizimine verilmiştir.
Cevap #2
React.FC, bir React bileşenini yazmanın tercih edilen yolu değildir, işte bir bağlantı.
Ben şahsen bu türü kullanıyorum:
const Component1 = ({ prop1, prop2 }): JSX.Element => { /*...*/ }
React.FC dezavantajlarının kısa listesi:
- Bileşeninizin çocuklara sahip olması gerekmediğinde bile, çocukların örtük bir tanımını sağlar. Bu bir hataya neden olabilir.
- Jenerikleri desteklemiyor.
defaultPropsile doğru çalışmıyor.
Cevap #3
En iyi çözüm:
İkinci yaklaşım + bir dönüş türü
const PrintName2 = ({ prop1, prop2 }: Props): JSX.Element => { /** */}
Bu size Props üzerinde tam kontrol sağlar ve daha açıktır (gizli bir sihir yoktur).
React.FC'yi kaldırmak için GitHub PR bağlantısı
Kent C Dodds bunun neden burada olduğuna dair bazı düşüncelere sahip
Optimal olmayan çözüm:
İlk sürüm (React.FC) sizin için birkaç tür ekleyecektir - bunlar React Tip Tanımlamalarından gelir
interface FunctionComponent<P = {}> {
(props: PropsWithChildren<P>, context?: any): ReactElement | null;
propTypes?: WeakValidationMap<P>;
contextTypes?: ValidationMap<any>;
defaultProps?: Partial<P>;
displayName?: string;
}
Bu yaklaşım birkaç nedenle yararlıdır, ancak bariz olanı şudur: Eğer bileşeninizin çocukları varsa, o zaman manuel olarak bir children özelliği eklemenize gerek yoktur. İyi değildir çünkü varsayılan özelliklerle ilgili sorunlar vardır ve birçok bileşenin çocukları yoktur.
Cevap #4
React ve TypeScript kullandığınız için, her zaman ilk deseni kullanmalısınız, çünkü bu, PrintName'in React Fonksiyonel Bileşen türünde olacağını ve Props türünde props alacağını ima ettiğinden, bileşeninizin daha sıkı şekilde yazı türünde olmasını sağlayacaktır.
const PrintName: React.FC<Props>
Fonksiyonel Bileşenler için tam arayüz tanımını React TypeScript tipleri deposunda okuyabilirsiniz.
Verdiğiniz ikinci örnek, Props türünde bir dizi parametre alan ve genel olarak herhangi bir şey döndürebilecek bir fonksiyon olduğunu dışında hiçbir tür belirtimi sağlamıyor.
Bu nedenle, yazmak
const PrintName2 = (props:Props)
benzer
const PrintName2: JSX.Element = (props:Props)
TypeScript'in bunun bir Fonksiyonel Bileşen olduğunu otomatik olarak çıkaramayacağı kesin.
