टाइपस्क्रिप्ट का उपयोग करके रिएक्ट घटक में डिफ़ॉल्ट गुण मान


153

मैं टाइपस्क्रिप्ट का उपयोग करके अपने घटकों के लिए डिफ़ॉल्ट संपत्ति मान सेट करने का तरीका नहीं जान सकता।

मूल कोड यही है:

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>
        );
    }
}

और जब मैं इस तरह से घटक का उपयोग करने की कोशिश करता हूं:

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

मुझे एक त्रुटि fooमिली है जिसमें कहा गया है कि संपत्ति गायब है। मैं डिफ़ॉल्ट मान का उपयोग करना चाहता हूं। मैंने भी static defaultProps = ...घटक के अंदर उपयोग करने की कोशिश की है , लेकिन इसका कोई प्रभाव नहीं पड़ा क्योंकि मुझे संदेह था।

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

मैं डिफ़ॉल्ट संपत्ति मूल्यों का उपयोग कैसे कर सकता हूं? कई JS घटक मेरी कंपनी उन पर भरोसा करती है और उनका उपयोग नहीं करना एक विकल्प नहीं है।


static defaultPropsसही है। क्या आप उस कोड को पोस्ट कर सकते हैं?
आरोन बेयल

जवाबों:


327

डिफ़ॉल्ट घटक वर्ग घटक के साथ

का उपयोग करना static defaultPropsसही है। आपको प्रॉपर और स्टेट के लिए इंटरफेसेस का इस्तेमाल करना चाहिए, न कि क्लासेस का।

अपडेट 2018/12/1 : टाइपस्क्रिप्ट ने defaultPropsसमय के साथ संबंधित प्रकार की जाँच में सुधार किया है । पुराने उपयोगों और मुद्दों के लिए नीचे नवीनतम और सबसे बड़े उपयोग के लिए पढ़ें।

टाइपस्क्रिप्ट 3.0 और ऊपर के लिए

टाइपस्क्रिप्ट ने विशेष रूप से टाइप-चेकिंग कार्य करने के लिए समर्थन जोड़ा हैdefaultProps कि आप कैसे उम्मीद करेंगे। उदाहरण:

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>
        );
    }
}

जिसे प्रस्तुत किया जा सकता है और एक fooविशेषता को पारित किए बिना संकलित किया जा सकता है :

<PageComponent bar={ "hello" } />

ध्यान दें कि:

टाइपस्क्रिप्ट 2.1 के लिए 3.0 तक

इससे पहले कि टाइपस्क्रिप्ट 3.0 defaultPropsआपके लिए कंपाइलर समर्थन लागू करता है, तब भी आप इसका उपयोग कर सकते हैं, और इसने 100% प्रतिक्रिया के साथ रनटाइम पर काम किया है, लेकिन चूंकि टाइपस्क्रिप्ट केवल जेएसएक्स विशेषताओं की जांच करते समय आपको प्रॉपर माना जाता है, आपको उन प्रॉपर को चिह्नित करना होगा जिनके पास वैकल्पिक के रूप में चूक है ?। उदाहरण:

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>
        );
    }
}

ध्यान दें कि:

  • यह एक अच्छा विचार है कि इसके defaultPropsसाथ एनोटेट करें Partial<>ताकि यह आपके प्रॉप्स के खिलाफ टाइप-चेक करे, लेकिन आपको प्रत्येक आवश्यक संपत्ति को डिफ़ॉल्ट मान के साथ आपूर्ति करने की आवश्यकता नहीं है, जो कि कोई मतलब नहीं है क्योंकि आवश्यक गुणों को कभी भी डिफ़ॉल्ट की आवश्यकता नहीं होनी चाहिए।
  • का उपयोग strictNullChecksकरते समय this.props.fooहोगा possibly undefinedऔर हटाने के लिए एक गैर अशक्त (यानी this.props.foo!) या टाइप-गार्ड (यानी if (this.props.foo) ...) की आवश्यकता होगी undefined। यह डिफ़ॉल्ट प्रोप मूल्य के बाद से कष्टप्रद है इसका मतलब है कि यह वास्तव में अपरिभाषित नहीं होगा, लेकिन टीएस ने इस प्रवाह को नहीं समझा। कि मुख्य कारणों में से एक है TS 3.0 में स्पष्ट समर्थन जोड़ा गया है defaultProps

टाइपस्क्रिप्ट 2.1 से पहले

यह समान काम करता है, लेकिन आपके पास Partialप्रकार नहीं होते हैं, इसलिए केवल Partial<>सभी आवश्यक प्रॉप्स के लिए डिफ़ॉल्ट मान और या तो डिफ़ॉल्ट मानों की आपूर्ति करें (भले ही उन डिफ़ॉल्ट का उपयोग कभी नहीं किया जाएगा) या स्पष्ट प्रकार एनोटेशन को पूरी तरह से छोड़ दें।

डिफ़ॉल्ट कार्यात्मक घटकों के साथ सहारा

आप defaultPropsफ़ंक्शन घटकों पर भी उपयोग कर सकते हैं , लेकिन आपको अपना फ़ंक्शन FunctionComponent( संस्करण से पहले ) इंटरफ़ेस StatelessComponentमें टाइप करना होगा ताकि टाइपस्क्रिप्ट फ़ंक्शन के बारे में जान सके:@types/react16.7.2defaultProps

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

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

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

ध्यान दें कि आपको टीएस 2.1+ में आंशिक के रूप में पहले से निर्दिष्ट होने के Partial<PageProps>कारण कहीं भी उपयोग करने की आवश्यकता नहीं है FunctionComponent.defaultProps

एक और अच्छा विकल्प (यह वही है जो मैं उपयोग करता हूं) अपने propsमापदंडों को नष्ट करना और डिफ़ॉल्ट मानों को सीधे असाइन करना है:

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

तो फिर तुम बिल्कुल जरूरत नहीं है defaultProps! ध्यान रखें कि यदि आप एक फ़ंक्शन घटक पर प्रदान करते हैं, तोdefaultProps यह डिफ़ॉल्ट पैरामीटर मानों पर वरीयता लेगा, क्योंकि रिएक्ट हमेशा defaultPropsमानों को स्पष्ट रूप से पारित करेगा (इसलिए पैरामीटर कभी अपरिभाषित नहीं होते हैं, इस प्रकार डिफ़ॉल्ट पैरामीटर का उपयोग कभी नहीं किया जाता है।) तो आप उपयोग करेंगे। एक या दूसरे, दोनों नहीं।


2
त्रुटि आपको लगता है जैसे आप प्रोप <PageComponent>को पारित किए बिना कहीं उपयोग कर रहे हैं foo। आप इसे foo?: stringअपने इंटरफ़ेस में उपयोग करके वैकल्पिक बना सकते हैं ।
आरोन बेयेल

1
@Aaron लेकिन tsc संकलन त्रुटि को फेंक देगा, क्योंकि defaultProps पेजप्रॉप्स इंटरफ़ेस को लागू नहीं करता है। आपको या तो सभी इंटरफ़ेस गुणों को वैकल्पिक (खराब) बनाना होगा या सभी आवश्यक फ़ील्ड (अनावश्यक बॉयलरप्लेट) के लिए डिफ़ॉल्ट मान भी निर्दिष्ट करना होगा या डिफ़ॉल्टप्रॉप्स पर निर्दिष्ट प्रकार से बचना होगा।
पेमेलस

1
@adrianmoisa आप डिफ़ॉल्ट सहारा का मतलब है? हाँ, यह काम करता है, लेकिन वाक्यविन्यास अलग है ... मैं अपने जवाब में एक उदाहरण जोड़ूंगा जब मैं अपने कंप्यूटर पर वापस आऊंगा ...
हारून बिएल

1
@ एड्रियनमोइसा अपडेटेड फंक्शन घटक उदाहरण के साथ
आरोन बाइलल

1
@Jared हाँ, इसे ठीक से काम करने के लिए सब कुछ (कंपाइलर और रिएक्ट रनटाइम) होना public static defaultPropsया static defaultProps( publicडिफ़ॉल्ट होना) चाहिए । इसके साथ रनटाइम पर काम कर सकते हैं private static defaultPropsसिर्फ इसलिए privateऔर publicरनटाइम पर मौजूद नहीं है, लेकिन संकलक सही ढंग से काम नहीं होता।
हारून बीलल

18

टाइपस्क्रिप्ट 2.1+ के साथ, अपने इंटरफ़ेस गुणों को वैकल्पिक बनाने के बजाय आंशिक <T> का उपयोग करें।

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

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

6

टाइपस्क्रिप्ट 3.0 के साथ इस समस्या का एक नया समाधान है:

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 />

ध्यान दें कि इसके लिए आपको एक नए संस्करण की आवश्यकता @types/reactहै 16.4.6। इसके साथ काम करता है 16.4.11


बहुत बढ़िया जवाब! कोई कैसे संभाल सकता है: export interface Props { name?: string;}जहां एक वैकल्पिक नाम है ? मैं TS2532 Object is possibly 'undefined'
पाती रहती

@ फ़ायडो के लिए मुझे एक वैकल्पिक प्रोप के लिए डिफ़ॉल्ट मान की आवश्यकता नहीं है, क्योंकि undefinedउन प्रॉप्स के लिए स्वचालित डिफ़ॉल्ट मान का एक प्रकार है। आप undefinedकभी-कभी स्पष्ट मान के रूप में पारित करने में सक्षम होना चाहते हैं , लेकिन एक और डिफ़ॉल्ट मान है? क्या आपने export interface Props {name: string | undefined;}इसके बजाय कोशिश की है ? कोशिश नहीं की है, बस एक विचार है।
CorayThan

जोड़ना जोड़ने ?के समान है |undefined। मैं वैकल्पिक रूप से प्रोप में पास करना चाहता हूं, और defaultPropsउस मामले को संभालना चाहता हूं । ऐसा लगता है कि TS3 में अभी तक यह संभव नहीं है। name!जब से मुझे पता है कि सेट undefinedहोने के बाद मैं सिर्फ खूंखार वाक्य रचना का उपयोग करूंगा defaultProps। फिर भी धन्यवाद!
14

1
Upvoted क्योंकि यह अब सही जवाब है! इस नई सुविधा के साथ मेरे स्वीकृत उत्तर (जो एक इतिहास की किताब बनने लगी है) को अद्यतन किया, और थोड़ा और स्पष्टीकरण दिया। :)
हारून बीलल

5

उन वैकल्पिक प्रॉप्स के लिए जिन्हें डिफ़ॉल्ट मानों की आवश्यकता होती है। यहाँ क्रेडिट :)

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 द्वारा एक टिप्पणी से:

आपको या तो सभी इंटरफ़ेस प्रॉपर्टीज़ को वैकल्पिक (खराब) करना होगा या सभी आवश्यक फ़ील्ड (अनावश्यक बॉयलरप्लेट) के लिए डिफ़ॉल्ट मान भी निर्दिष्ट करना होगा या डिफ़ॉल्टप्रॉप्स पर निर्दिष्ट प्रकार से बचना होगा।

वास्तव में आप टाइपस्क्रिप्ट के इंटरफ़ेस वंशानुक्रम का उपयोग कर सकते हैं । परिणामी कोड केवल थोड़ी अधिक क्रिया है।

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

कार्यात्मक घटक के लिए, मैं propsतर्क रखना चाहूंगा , इसलिए यहां मेरा समाधान है:

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

कार्यात्मक घटक

दरअसल, कार्यात्मक घटक के लिए सबसे अच्छा अभ्यास नीचे की तरह है, मैं एक नमूना स्पिनर घटक बनाता हूं:

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;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.