본문 바로가기

개발하자

TypeScript를 사용하는 React 구성 요소의 기본 속성 값

반응형

TypeScript를 사용하는 React 구성 요소의 기본 속성 값

Typescript를 사용하여 구성 요소의 기본 속성 값을 설정하는 방법을 알 수 없습니다.

소스 코드는 다음과 같습니다.

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

숙박업소가 누락되었다는 오류가 발생합니다. 기본값을 사용하고 싶습니다. 부품 내부도 사용해봤지만, 예상대로 효과가 없었습니다.

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

기본 속성 값을 사용하려면 어떻게 해야 합니까? 우리 회사에서 사용하는 많은 JS 부품들은 그것들에 의존하며 그것들을 사용하지 않는 것은 선택이 아니다.




클래스 구성요소가 있는 기본 소품

사용이 맞습니다. 또한 소품 및 상태를 위해 클래스가 아닌 인터페이스를 사용해야 합니다.

2018/12/1 업데이트: TypeScript는 시간 경과와 관련된 유형 검사를 개선했습니다. 이전 사용 및 문제까지 최신 및 최대 사용량에 대한 내용을 읽어 보십시오.

TypeScript 3.0 이상의 경우

특히 Script를 입력하여 원하는 대로 유형 검사를 수행합니다. 예:

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

속성을 전달하지 않고 렌더링하고 컴파일할 수 있습니다.

<PageComponent bar={ "hello" } />

주의:

  • 는 JSX 속성으로 필요하지 않은 경우에도 선택 사항(즉)으로 표시됩니다. 선택 사항으로 표시한다는 것은 그럴 수 있다는 것을 의미하지만, 실제로는 기본값을 제공하기 때문에 그럴 수 없습니다. 방법과 비슷하게 생각해 보세요. TypeScript 3.0+는 유사한 방식으로 처리하는데, 이는 리액트 사용자에게 정말 멋진 일입니다!
  • 에는 명시적 형식 주석이 없습니다. 이 유형은 컴파일러가 어떤 JSX 속성이 필요한지 결정하기 위해 추론하고 사용합니다. 의 하위 집합과 일치하는지 확인하는 데 사용할 수 있습니다. 이 주의 사항에 대한 자세한 내용은 다음과 같습니다.
  • 이렇게 하려면 버전이 제대로 작동해야 합니다.

TypeScript 2.1 ~ 3.0의 경우

TypeScript 3.0이 컴파일러 지원을 구현하기 전에는 여전히 사용할 수 있었고 런타임에 React에서 100% 작동했지만 TypeScript는 JSX 속성을 확인할 때 소품만 고려했기 때문에 기본값이 있는 소품을 옵션으로 표시해야 합니다. 예:

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

주의:

  • 소품에 대해 유형 검사를 수행할 수 있도록 주석을 다는 것은 좋은 생각이지만 필요한 모든 속성을 기본값으로 제공할 필요는 없습니다. 필요한 속성은 기본값을 필요로 하지 않기 때문에 의미가 없습니다.
  • 의 값을 사용하는 경우 을(를) 제거할 Null이 아닌 어설션(즉, ) 또는 유형 가드(를)가 필요합니다. 기본 prop 값은 실제로 정의되지 않는다는 것을 의미하지만 TS는 이 흐름을 이해하지 못했습니다. 이것이 TS 3.0이 에 대한 명시적 지원을 추가한 주요 이유 중 하나입니다.

TypeScript 2.1 이전 버전

이 작업은 동일하게 작동하지만 유형이 없으므로 필요한 모든 소품에 대한 기본값을 생략하고 제공하거나(기본값이 사용되지 않더라도) 명시적 유형 주석을 완전히 생략합니다.

다음 기본 소품

함수 구성 요소에서도 사용할 수 있지만 TypeScript가 함수에 대해 알 수 있도록 (이전 버전) 인터페이스에 함수를 입력해야 합니다.

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+에서 이미 파셜로 지정되어 있으므로 아무 곳에서도 사용할 필요가 없습니다.

다른 좋은 대안(이것이 제가 사용하는 것입니다)은 매개 변수를 해체하고 기본값을 직접 할당하는 것입니다.

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

그럼 당신은 전혀 필요가 없겠군요! 함수 구성 요소에 제공할 경우 React는 항상 명시적으로 값을 전달하므로(따라서 매개 변수가 정의되지 않으므로 기본 매개 변수는 사용되지 않음) 기본 매개 변수 값보다 우선합니다. 둘 다 말고 둘 중 하나를 사용하겠죠.




승인된 답변에 대한 @pamelus의 논평에서:

모든 인터페이스 속성을 선택사항(불량)으로 만들거나 모든 필수 필드(불필요한 보일러 플레이트)에 대한 기본값을 지정하거나 defaultProps에서 유형을 지정하지 않도록 해야 합니다.

실제로 Typescript's를 사용할 수 있습니다. 결과 코드는 조금 더 장황할 뿐이다.

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



Typescript 2.1+에서는 인터페이스 속성을 옵션으로 만드는 대신 사용합니다.

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

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



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

이 작업을 수행하려면 의 최신 버전이 필요합니다. 와 함께 작동합니다.




기본값이 필요한 선택적 소품을 사용하는 경우.

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



기능 구성요소의 경우, 인수를 유지하는 것이 더 낫습니다. 따라서 제 해결책은 다음과 같습니다.

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;



기능 구성 요소

실제로 기능 구성요소의 모범 사례는 다음과 같습니다. Spinner 구성요소의 샘플을 작성합니다.

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

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

const Spinner = ({
  color = colors.primary,
  size = 'small',
  animating = true,
  hidesWhenStopped = true,
}: SpinnerProps): JSX.Element => (
  <ActivityIndicator
    color={color}
    size={size}
    animating={animating}
    hidesWhenStopped={hidesWhenStopped}
  />
);

export default Spinner;

구성 요소가 있는 경우 다음과 같이 사용하는 것이 좋습니다.

export interface TypographyProps {
  color?: string;
}

const Typography: React.FC<TypographyProps> = ({
  children,
  color,
}) => (
  <span style={{ color }}>
    {children}
  </span>
);

export default Typography;



스프레드 연산자를 사용하여 표준 기능 구성요소로 소품을 재할당할 수 있습니다. 이 접근 방식의 좋은 점은 필수 소품과 기본값이 있는 선택적 소품을 혼합할 수 있다는 것입니다.

interface MyProps {
   text: string;
   optionalText?: string;
}

const defaultProps = {
   optionalText = "foo";
}

const MyComponent = (props: MyProps) => {
   props = { ...defaultProps, ...props }
}



후크(유형 스크립트 포함)

export interface ApprovalRejectModalProps{
 singleFileApprove:boolean;
}

ApproveRejectModal.defaultProps={
 singleFileApprove:false --> default value
}

export const ApproveRejectModal:React.FC<ApprovalRejectModalProps>=(props)=>{
return (
        <div>
            ....
        </div>
       )
}



기능 구성 요소를 위한 및 소품 포함(타입스크립트 4.4+):

export const LoadingSpinner = ({
  size = "lg",
  children,
}: {
  size?: "sm" | "base" | "lg";
  children?: any;
}) => {
console.log(size);
return <div>{children}</div>
};

다음과 같이 사용합니다.

 <LoadingSpinner size="sm"><p>hello</p></LoadingSpinner>
 <LoadingSpinner><p>hello</p></LoadingSpinner>




너무 과장된 대답들이 많은 것 같은데...

인라인 삼진법만 사용하면... 이 예에서 상자 그림자가 제공되지 않으면 기본값은 'module'이고, 값이 제공되면 해당 값입니다.

export interface FormItemProps {
  boxShadow?: boolean;
  marginBottom: string;
}

export const FormItem = (props: FormItemProps) => {
  return (
    <div
      style={{marginBottom: props.marginBottom,}}
    >
     
      <div            
        style={{boxShadow: props.boxShadow ? props.boxShadow : 'none',}}
      >
        {'some text..... '}
      </div>
    </div>
  );
};



솔루션 확인:

interface Props {
  foo?: string | undefined;
  bar: string;
  other?: string;
}

export const Component = ({foo, bar, other = 'default text'}:Props) => {
    console.log(foo, bar, other);
    return(
        ...//some cool stuff your component should do
    )
}

<Component bar='obligatory text'/>

반응형