source

일반 상태 비저장 구성 요소 반응 유형?또는 일반 기능 인터페이스를 더 일반적이 되도록 타이프스크립트로 확장합니까?

bestscript 2023. 2. 22. 22:30

일반 상태 비저장 구성 요소 반응 유형?또는 일반 기능 인터페이스를 더 일반적이 되도록 타이프스크립트로 확장합니까?

문제:의 인터페이스Stateless Functional Component라고 되어

interface SFC<P = {}> {
    (props: P & { children?: ReactNode }, context?: any): ReactElement<any> | null;
    propTypes?: ValidationMap<P>;
}

컴포넌트의 프로펠러 타입은 다음과 같습니다.

interface Prop<V>{
    num: V;
}

컴포넌트를 적절하게 정의하는 방법다음과 같이 합니다.

const myCom: <T>SFC<Prop<T>> = <T>(props: Prop<T>)=> <div>test</div>

character 27 그그Cannot find name 'T'

다음은 Typescript Playground of modified example 입니다.

마이 파인딩:

1: Typescript 2.9.1 지원 스테이트풀 범용 컴포넌트

class myCom<T> extends React.Component<Prop<T>, any> {
   render() {
      return <div>test</div>;
   }
}

내선2: 장SFC다음 답변에 언급된 것과 같이 새로운 인터페이스를 만드는 것은 구성 요소의 받침 유형을 다음과 같이 만들 것입니다.any: Typscript 원하지 않는 일반 파라미터/반환 타입으로 상태 비저장 함수 반응.내 소품에 적절한 활자를 주고 싶다.

제네릭스는 다음과 같이 사용할 수 없습니다.

const myCom: <T>SFC<Prop<T>> = <T>(props: Prop<T>)=> <div>test</div>

TypeScript 사양은 다음과 같습니다.

형상의 구성

< T > ( ... ) => { ... }

형식 매개 변수가 있는 화살표 함수 식 또는 형식 매개 변수가 없는 화살표 함수에 적용되는 형식 어설션으로 구문 분석할 수 있습니다.

소스: Microsoft/TypeScript spec.md

선언이 TypeScript 사양에 정의된 패턴과 일치하지 않으므로 동작하지 않습니다.

단, SFC 인터페이스는 사용하지 않고 직접 선언할 수 있습니다.

interface Prop<V> {
    num: V;
}

// normal function
function Abc<T extends string | number>(props: Prop<T>): React.ReactElement<Prop<T>> {
    return <div />;
}

// const lambda function
const Abc: <T extends string | number>(p: Prop<T>) => React.ReactElement<Prop<T>> = (props) => {
   return <div />
};

export default function App() {
    return (
        <React.Fragment>
            <Abc<number> num={1} />
            <Abc<string> num="abc" />
            <Abc<string> num={1} /> // string expected but was number
        </React.Fragment>
    );
}

컴포넌트 외부에 범용 컴포넌트 타입의 에일리어스를 선언하고, 필요에 따라서 에일리어스를 아사트 하는 것으로, 이 문제를 경감하는 패턴이 있습니다.

예쁘지는 않지만 재사용이 가능하고 엄격합니다.

interface IMyComponentProps<T> {
  name: string
  type: T
}

// instead of inline with component assignment
type MyComponentI<T = any> = React.FC<IMyComponentProps<T>>

const MyComponent: MyComponentI = props => <p {...props}>Hello</p>

const TypedComponent = MyComponent as MyComponentI<number>

공장 패턴:

import React, { SFC } from 'react';

export interface GridProps<T = unknown> {
  data: T[];
  renderItem: (props: { item: T }) => React.ReactChild;
}

export const GridFactory = <T extends any>(): SFC<GridProps<T>> => () => {
  return (
    <div>
      ...
    </div>
  );
};

const Grid = GridFactory<string>();

업데이트: 2021년 3월 8일

후크 에러 규칙을 회피하려면 , 다음과 같은 구문을 미세하게 할 필요가 있습니다.

import React, { FC } from 'react';

export interface GridProps<T = unknown> {
  data: T[]
  renderItem: (props: { item: T }) => React.ReactChild
}

export const GridFactory = <T extends any>() => {
  const Instance: FC<GridProps<T>> = (props) => {
    const [state, setState] = useState(props.data)

    return <div>...</div>
  }

  return Instance
}

const Grid = GridFactory<string>()

비슷하지만 약간 다른 해결책을 제안합니다(친구와 브레인스토밍).Formik 래퍼를 작성하려고 했는데, 다음과 같은 방법으로 작업을 할 수 있었습니다.

import React, { memo } from 'react';

export type FormDefaultProps<T> = {
  initialValues: T;
  onSubmit<T>(values: T, actions: FormikActions<T>): void;
  validationSchema?: object;
};

// We extract React.PropsWithChildren from React.FunctionComponent or React.FC
function component<T>(props: React.PropsWithChildren<FormDefaultProps<T>>) {
  // Do whatever you want with the props.
  return(<div>{props.children}</div>
}

// the casting here is key. You can use as typeof component to 
// create the typing automatically with the generic included..
export const FormDefault = memo(component) as typeof component;

그런 다음, 이렇게 사용합니다.

 <FormDefault<PlanningCreateValues>
        onSubmit={handleSubmit}
        initialValues={PlanningCreateDefaultValues}
      >
         {/*Or any other child content in here */}
        {pages[page]}
</FormDefault>

메서드 표현으로는 이 작업을 수행할 수 없습니다.

const a: React.FC<MyProp> = (prop) => (<>MyComponent</>);

@chris가 제시한 공장 패턴은 좋지만 리액트 훅을 사용할 수 없습니다.그래서 이걸 쓰고 있어요.

// Props
interface Props<T> {
  a: T;
}

// Component
export const MyComponent: <T>(p: PropsWithChildren<Props<T>>) => React.ReactElement = props => {
  return <div>Hello Typescript</div>;
};

자녀가 필요하지 않은 경우 Propos With Children 부품을 제거할 수 있습니다.소품 분해 및 후크도 작동합니다.

export const MyComponent: <T>(p: Props<T>) => React.ReactElement = ({ a }) => {
  const [myState, setMyState] = useState(false);
  return <div>Hello Typescript</div>;
};

방법이 있긴 한데 완벽한지 아닌지는 잘 모르겠어요.

interface ComponentProps<T> {
    text: T;
}

export const Component= <T,>(props: ComponentProps<T>) => {
  const { text } = props
  const [s] = useState(0) // you can use hook
  return (<div>yes</div>)
}

다음과 같이 컴포넌트를 사용할 수 있습니다.

 (
  <>
    <Component<string> text="some text" />
  </>
 )

유형 정의에 React의 Function Component 유형을 포함하려면(예를 들어 반환 유형이 자동으로 선택되도록 하기 위해), 유형을 약간 반복해도 괜찮다면 다음과 같은 구성을 사용할 수 있습니다.

interface MyProps<T> {
  val: T
}

const Component: React.FC<MyProps<any>> = <T>({
  val
}: MyProps<T>) => {
  // Your code and hooks here
  return <div>Heya</div>
}

Const 유형ComponentReact.FC<MyProps<any>>즉, 이 값은 에 대해 유효한 값으로 사용할 수 있습니다.MyPropstype 파라미터T단, 구현에 의해 범용 타입 파라미터가 재지정되었기 때문에T구현 코드 내 타입은 다음과 같습니다.T가 아니라any이 때문에, 올바르게 타이프 체크됩니다. T다음과 같은 제한적인 지정자를 가질 수 있습니다.extends string인터페이스 사양과 기능 실장 시그니처 양쪽에서 이들 명령어를 반복하기만 하면 됩니다.

jmattheis 게시물에 따른 일반 상태 비저장 구성 요소의 예입니다.

MyGenericStatelessComponent.tsx

import React from "react";

type Prop<T> = {
    example: T;
};

const MyGenericStatelessComponent: <T extends Record<string, number | string>>(props: Prop<T>) => JSX.Element = <
    T extends Record<string, unknown>
>(
    props: Prop<T>
): JSX.Element => {
    return (
        <div>
            Example Prop id: {props.example.id}, Example Prop name: {props.example.name}
        </div>
    );
};

export default MyGenericStatelessComponent;

사용방법:

<MyGenericStatelessComponent example={{ id: 1, name: "test01" }} />

사용.T = any@vadistic의 예에서는 동작하지만 타입 체크는 할 수 없습니다.이 코드를 사용하면 코드 완성 및 입력 확인이 가능합니다.

interface IProps<TModel> extends RouteComponentProps {
    headerText?: string | React.ReactNode;
    collection: TModel[];
}

interface ICommonSortableType extends ISortableItem {
    id: number;
    isCorrectResponse: boolean;
}

interface ISortableItem {
    sortableId: number;
}    

type GenericFunctionalComponent<TModel> = React.FC<IProps<TModel>>;
const CommonSortableList: GenericFunctionalComponent<ICommonSortableType> = (props) => {
...
}

다음으로 다음과 같이 사용할 수 있습니다.

class CommonSortableType {
    public sortableId: number = -1;
    public id: number = -1;
    public isCorrectResponse: boolean = false;
}

<CommonSortableList
    collection={item.commonSortableTypes} //Is CommonSortableType[]
    headerText={<FormattedMessage id="item.list" />}
</CommonSortableList>

class ExtendedOptionDto extends OptionDto implements ICommonSortableType {
    public sortableId: number = -1;
}

class OptionDto {
    public id: number = -1;
    public isCorrectResponse: boolean = false;
}

<CommonSortableList
    collection={item.extendedOptionDtos} //Is ExtendedOptionDto[]
    headerText={<FormattedMessage id="item.list" />}
</CommonSortableList>

언급URL : https://stackoverflow.com/questions/51459971/type-of-generic-stateless-component-react-or-extending-generic-function-interfa