TypeScript kullanarak React bileşenindeki varsayılan özellik değeri


153

Typescript kullanarak bileşenlerim için varsayılan özellik değerlerini nasıl ayarlayacağımı anlayamıyorum.

Bu kaynak kod:

class PageState
{
}

export class PageProps
{
    foo: string = "bar";
}

export class PageComponent extends React.Component<PageProps, PageState>
{
    public render(): JSX.Element
    {
        return (
            <span>Hello, world</span>
        );
    }
}

Ve böyle bir bileşeni kullanmaya çalıştığımda:

ReactDOM.render(<PageComponent />, document.getElementById("page"));

Özellik fooeksik olduğunu bildiren bir hata alıyorum . Varsayılan değeri kullanmak istiyorum. Ayrıca static defaultProps = ...bileşen içinde kullanmayı denedim , ancak şüphelendiğim gibi bir etkisi olmadı.

src/typescript/main.tsx(8,17): error TS2324: Property 'foo' is missing in type 'IntrinsicAttributes & IntrinsicClassAttributes<PageComponent> & PageProps & { children?: ReactEle...'.

Varsayılan özellik değerlerini nasıl kullanabilirim? Şirketimin kullandığı birçok JS bileşeni bunlara güveniyor ve kullanmamak bir seçenek değil.


static defaultPropsdoğru. Bu kodu gönderebilir misiniz?
Aaron Beall

Yanıtlar:


327

Sınıf bileşeniyle varsayılan aksesuarlar

Kullanımı static defaultPropsdoğrudur. Ayrıca sahne ve durum için sınıfları değil arabirimleri kullanıyor olmalısınız.

2018/12/1 Güncellemesi : TypeScript, defaultPropszamanla ilişkili tür kontrolünü geliştirdi . Eski kullanımlara ve sorunlara kadar en son ve en iyi kullanım için okumaya devam edin.

TypeScript 3.0 ve üstü için

TypeScript , tür denetlemenin beklediğiniz gibi çalışmasını sağlamak içindefaultProps özel olarak destek ekledi . Misal:

interface PageProps {
  foo: string;
  bar: string;
}

export class PageComponent extends React.Component<PageProps, {}> {
    public static defaultProps = {
        foo: "default"
    };

    public render(): JSX.Element {
        return (
            <span>Hello, { this.props.foo.toUpperCase() }</span>
        );
    }
}

Bir fooniteliği geçmeden oluşturulabilir ve derlenebilir :

<PageComponent bar={ "hello" } />

Bunu not et:

TypeScript 2.1 - 3.0 arası

TypeScript 3.0 defaultPropssizin için derleyici desteğini uygulamadan önce yine de yararlanabiliyordu ve çalışma zamanında React ile% 100 çalıştı, ancak TypeScript yalnızca varsayılan olarak JSX özelliklerini denetlerken sahne donanımlarını isteğe bağlı olarak işaretlemeniz gerektiğinden ?. Misal:

interface PageProps {
    foo?: string;
    bar: number;
}

export class PageComponent extends React.Component<PageProps, {}> {
    public static defaultProps: Partial<PageProps> = {
        foo: "default"
    };

    public render(): JSX.Element {
        return (
            <span>Hello, world</span>
        );
    }
}

Bunu not et:

  • Bu açıklama yaparak iyi bir fikirdir defaultPropsile Partial<>sizin sahne karşı bu yüzden o tip-çekler, ancak gerekli özellikleri bir varsayılan gerekli olmaması gereken beri hiç mantıklı bir varsayılan değer olan her Gerekli özelliğini temin gerekmez.
  • Kullanırken strictNullChecksdeğeri this.props.fooolacak possibly undefinedve geçersiz olmayan bir iddiayı (yani this.props.foo!) veya tip koruyucuyu (yani if (this.props.foo) ...) kaldırmak gerekir undefined. Varsayılan pervane değeri, aslında asla tanımlanmayacağı anlamına gelir, ancak TS bu akışı anlamadı. TS 3.0'ın açık destek vermesinin ana nedenlerinden biri budur defaultProps.

TypeScript 2.1'den önce

Bu aynı şekilde çalışır, ancak Partialtürleriniz yoktur, bu nedenle Partial<>tüm gerekli sahne için varsayılan değerleri atlayın ve sağlayın (bu varsayılanlar asla kullanılmayacak olsa bile) veya açık tür ek açıklamasını tamamen atlayın.

Fonksiyonel Bileşenler ile varsayılan aksesuarlar

Sen kullanabilirsiniz defaultPropsyanı fonksiyon bileşenleri üzerinde, ancak sizin işlevi yazmak zorunda FunctionComponent( StatelessComponentiçinde @types/reactversiyonundan önce 16.7.2typescript biliyor ki) arayüzüne defaultPropsfonksiyonu üzerine:

interface PageProps {
  foo?: string;
  bar: number;
}

const PageComponent: FunctionComponent<PageProps> = (props) => {
  return (
    <span>Hello, {props.foo}, {props.bar}</span>
  );
};

PageComponent.defaultProps = {
  foo: "default"
};

TS 2.1+ sürümünde kısmi olarak belirtilmiş Partial<PageProps>olduğundan hiçbir yerde kullanmanız gerekmediğini unutmayın FunctionComponent.defaultProps.

Başka bir güzel alternatif (kullandığım şey) propsparametrelerinizi yıkmak ve doğrudan varsayılan değerleri atamaktır:

const PageComponent: FunctionComponent<PageProps> = ({foo = "default", bar}) => {
  return (
    <span>Hello, {foo}, {bar}</span>
  );
};

O zaman hiç ihtiyacınız yok defaultProps! Eğer varsa unutmayın do sağlamak defaultPropsher zaman açıkça geçecek tepki çünkü bir işlev bileşende varsayılan parametre değerlerinin her zaman öncelikli olacaktır defaultProps(parametreler tanımsız asla böylece, böylece varsayılan parametre hiçbir zaman kullanılmaz.) Kullanmak istiyorum Yani değerlerini biri ya da diğeri, ikisi de değil.


2
Hata <PageComponent>, foopervaneyi geçmeden bir yerde kullandığınız gibi geliyor . foo?: stringArayüzünüzde kullanarak isteğe bağlı yapabilirsiniz .
Aaron Beall

1
@Aaron Ancak tsc derleme hatası atar, çünkü defaultProps PageProps arabirimini uygulamaz. Tüm arabirim özelliklerini isteğe bağlı (kötü) yapmalı veya gerekli tüm alanlar için de (gereksiz ısıtıcı) varsayılan değer belirtmelisiniz veya defaultProps üzerinde tür belirtmekten kaçınmalısınız.
pamelus

1
@adrianmoisa Yani varsayılan aksesuarlar mı demek istediniz? Evet işe yarıyor ama sözdizimi farklı ... Bilgisayarıma döndüğümde cevabım için bir örnek ekleyeceğim ...
Aaron Beall

1
@AdrianMoisa s işlev bileşeni örneği ile güncellendi
Aaron Beall

1
@Jared Evet, her şeyin (derleyici ve React çalışma zamanı) düzgün çalışması için public static defaultPropsveya static defaultProps( publicvarsayılan) olması gerekir. O ile zamanında çalışabilir private static defaultPropsçünkü privateve publicçalışma zamanında mevcut olmayan, fakat derleyici doğru işe yaramaz.
Aaron Beall

18

Typescript 2.1+ ile, arayüz özelliklerinizi isteğe bağlı yapmak yerine Kısmi <T> kullanın.

export interface Props {
    obj: Model,
    a: boolean
    b: boolean
}

public static defaultProps: Partial<Props> = {
    a: true
};

6

Typescript 3.0 ile bu soruna yeni bir çözüm var :

export interface Props {
    name: string;
}

export class Greet extends React.Component<Props> {
    render() {
        const { name } = this.props;
        return <div>Hello ${name.toUpperCase()}!</div>;
    }
    static defaultProps = { name: "world"};
}

// Type-checks! No type assertions needed!
let el = <Greet />

Bunun çalışması için daha yeni bir sürüme ihtiyacınız @types/reactolduğunu unutmayın 16.4.6. İle çalışır 16.4.11.


Mükemmel cevap! Biri nasıl işleyebilir: export interface Props { name?: string;}adı isteğe bağlı bir pervane? Ben almaya devamTS2532 Object is possibly 'undefined'
Fydo

@Fydo Opsiyonlar için varsayılan bir değere sahip olmam gerekmedi, çünkü undefinedbu aksesuarlar için bir tür otomatik varsayılan değer. undefinedBazen müstehcen değer olarak geçebilmek istiyorsunuz , ancak başka bir varsayılan değeriniz mi var? export interface Props {name: string | undefined;}Bunun yerine denedin mi? Bunu denemedim, sadece bir fikir.
CorayThan

Eklemek ?, eklemekle aynı şeydir |undefined. İsteğe bağlı olarak pervaneyi geçmek ve defaultPropsbu durumu ele almak istiyorum. Görünüşe göre TS3'te bu henüz mümkün değil. Sadece ne zaman ayarlanmadığını name!bildiğim için sadece korkunç sözdizimini kullanacağım . Yine de teşekkürler! undefineddefaultProps
Fydo

1
Oy verildi çünkü bu doğru cevap! Ayrıca kabul edilen cevabımı (tarih kitabı olmaya başlıyor) bu yeni özellik ve biraz daha açıklama ile güncelledi. :)
Aaron Beall

5

Varsayılan değerlere ihtiyaç duyan isteğe bağlı sahne donanımı olanlar için. Kredi burada :)

interface Props {
  firstName: string;
  lastName?: string;
}

interface DefaultProps {
  lastName: string;
}

type PropsWithDefaults = Props & DefaultProps;

export class User extends React.Component<Props> {
  public static defaultProps: DefaultProps = {
    lastName: 'None',
  }

  public render () {
    const { firstName, lastName } = this.props as PropsWithDefaults;

    return (
      <div>{firstName} {lastName}</div>
    )
  }
}

3

@Pamelus tarafından kabul edilen cevaba yapılan bir yorumdan:

Tüm arabirim özelliklerini isteğe bağlı (bozuk) yapmalı veya gerekli tüm alanlar için de (gereksiz kazan plakası) varsayılan değer belirtmelisiniz veya defaultProps üzerinde tür belirtmekten kaçınmalısınız.

Aslında Typescript'in arayüz devralmasını kullanabilirsiniz . Ortaya çıkan kod sadece biraz daha ayrıntılıdır.

interface OptionalGoogleAdsProps {
    format?: string;
    className?: string;
    style?: any;
    scriptSrc?: string
}

interface GoogleAdsProps extends OptionalGoogleAdsProps {
    client: string;
    slot: string;
}


/**
 * Inspired by https://github.com/wonism/react-google-ads/blob/master/src/google-ads.js
 */
export default class GoogleAds extends React.Component<GoogleAdsProps, void> {
    public static defaultProps: OptionalGoogleAdsProps = {
        format: "auto",
        style: { display: 'block' },
        scriptSrc: "//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"
    };

0

Fonksiyonel bileşen için, propsargümanı tutmayı tercih ederim , işte benim çözümüm:

interface Props {
  foo: string;
  bar?: number; 
}

// IMPORTANT!, defaultProps is of type {bar: number} rather than Partial<Props>!
const defaultProps = {
  bar: 1
}


// externalProps is of type Props
const FooComponent = exposedProps => {
  // props works like type Required<Props> now!
  const props = Object.assign(defaultProps, exposedProps);

  return ...
}

FooComponent.defaultProps = defaultProps;

0

Fonksiyonel Bileşen

Aslında, fonksiyonel bileşen için en iyi uygulama aşağıdaki gibidir, örnek bir Spinner bileşeni oluşturuyorum:

import React from 'react';
import { ActivityIndicator } from 'react-native';
import { colors } from 'helpers/theme';
import type { FC } from 'types';

interface SpinnerProps {
  color?: string;
  size?: 'small' | 'large' | 1 | 0;
  animating?: boolean;
  hidesWhenStopped?: boolean;
}

const Spinner: FC<SpinnerProps> = ({
  color,
  size,
  animating,
  hidesWhenStopped,
}) => (
  <ActivityIndicator
    color={color}
    size={size}
    animating={animating}
    hidesWhenStopped={hidesWhenStopped}
  />
);

Spinner.defaultProps = {
  animating: true,
  color: colors.primary,
  hidesWhenStopped: true,
  size: 'small',
};

export default Spinner;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.