유형 스크립트로 반응 - React.forwardRef 사용 시 일반 정보
사용자가 커스텀을 전달할 수 있는 범용 컴포넌트를 작성하려고 합니다.OptionType컴포넌트에 접속하여 타입을 체크합니다.이 컴포넌트에는React.forwardRef.
forwardRef 없이도 작동시킬 수 있습니다.좋은 생각 있어요?아래 코드:
Forward Ref.tsx 미포함
export interface Option<OptionValueType = unknown> {
value: OptionValueType;
label: string;
}
interface WithoutForwardRefProps<OptionType> {
onChange: (option: OptionType) => void;
options: OptionType[];
}
export const WithoutForwardRef = <OptionType extends Option>(
props: WithoutForwardRefProps<OptionType>,
) => {
const { options, onChange } = props;
return (
<div>
{options.map((opt) => {
return (
<div
onClick={() => {
onChange(opt);
}}
>
{opt.label}
</div>
);
})}
</div>
);
};
Forward Ref.tsx 포함
import { Option } from './WithoutForwardRef';
interface WithForwardRefProps<OptionType> {
onChange: (option: OptionType) => void;
options: OptionType[];
}
export const WithForwardRef = React.forwardRef(
<OptionType extends Option>(
props: WithForwardRefProps<OptionType>,
ref?: React.Ref<HTMLDivElement>,
) => {
const { options, onChange } = props;
return (
<div>
{options.map((opt) => {
return (
<div
onClick={() => {
onChange(opt);
}}
>
{opt.label}
</div>
);
})}
</div>
);
},
);
App.tsx
import { WithoutForwardRef, Option } from './WithoutForwardRef';
import { WithForwardRef } from './WithForwardRef';
interface CustomOption extends Option<number> {
action: (value: number) => void;
}
const App: React.FC = () => {
return (
<div>
<h3>Without Forward Ref</h3>
<h4>Basic</h4>
<WithoutForwardRef
options={[{ value: 'test', label: 'Test' }, { value: 1, label: 'Test Two' }]}
onChange={(option) => {
// Does type inference on the type of value in the options
console.log('BASIC', option);
}}
/>
<h4>Custom</h4>
<WithoutForwardRef<CustomOption>
options={[
{
value: 1,
label: 'Test',
action: (value) => {
console.log('ACTION', value);
},
},
]}
onChange={(option) => {
// Intellisense works here
option.action(option.value);
}}
/>
<h3>With Forward Ref</h3>
<h4>Basic</h4>
<WithForwardRef
options={[{ value: 'test', label: 'Test' }, { value: 1, label: 'Test Two' }]}
onChange={(option) => {
// Does type inference on the type of value in the options
console.log('BASIC', option);
}}
/>
<h4>Custom (WitForwardRef is not generic here)</h4>
<WithForwardRef<CustomOption>
options={[
{
value: 1,
label: 'Test',
action: (value) => {
console.log('ACTION', value);
},
},
]}
onChange={(option) => {
// Intellisense SHOULD works here
option.action(option.value);
}}
/>
</div>
);
};
에서App.tsx, 라고 써 있습니다.WithForwardRef구성 요소가 일반적이지 않습니다.이것을 달성할 수 있는 방법이 있나요?
보고서 예: https://github.com/jgodi/generics-with-forward-ref
감사합니다!
출력으로 범용 컴포넌트 생성React.forwardRef는 직접 가능하지 않습니다(하단 참조).몇 가지 대안이 있습니다.예를 들어 예를 간략하게 설명하겠습니다.
type Option<O = unknown> = { value: O; label: string; }
type Props<T extends Option<unknown>> = { options: T[] }
const options = [
{ value: 1, label: "la1", flag: true },
{ value: 2, label: "la2", flag: false }
]
단순성을 위해 변형 (1) 또는 (2)를 선택합니다. (3)이 대체됩니다.forwardRef늘 쓰는 소품으로.(4)를 통해 전 세계적으로 기회 제공forwardRef앱에 정의를 한 번 입력합니다.
1. 활자 어설션('캐스트')을 사용한다.
// Given render function (input) for React.forwardRef
const FRefInputComp = <T extends Option>(p: Props<T>, ref: Ref<HTMLDivElement>) =>
<div ref={ref}> {p.options.map(o => <p>{o.label}</p>)} </div>
// Cast the output
const FRefOutputComp1 = React.forwardRef(FRefInputComp) as
<T extends Option>(p: Props<T> & { ref?: Ref<HTMLDivElement> }) => ReactElement
const Usage11 = () => <FRefOutputComp1 options={options} ref={myRef} />
// options has type { value: number; label: string; flag: boolean; }[]
// , so we have made FRefOutputComp generic!
이것은, Return 타입으로서 기능합니다.forwardRef원칙적으로 단순한 함수입니다.일반적인 기능 타입의 모양만 있으면 됩니다.어설션을 간단하게 하기 위해 다른 유형을 추가할 수 있습니다.
type ForwardRefFn<R> = <P={}>(p: P & React.RefAttributes<R>) => ReactElement |null
// `RefAttributes` is built-in type with ref and key props defined
const Comp12 = React.forwardRef(FRefInputComp) as ForwardRefFn<HTMLDivElement>
const Usage12 = () => <Comp12 options={options} ref={myRef} />
2. 전달된 컴포넌트를 랩으로 감습니다.
const FRefOutputComp2 = React.forwardRef(FRefInputComp)
// ↳ T is instantiated with base constraint `Option<unknown>` from FRefInputComp
export const Wrapper = <T extends Option>({myRef, ...rest}: Props<T> &
{myRef: React.Ref<HTMLDivElement>}) => <FRefOutputComp2 {...rest} ref={myRef} />
const Usage2 = () => <Wrapper options={options} myRef={myRef} />
3. 생략forwardRef다같이
대신 커스텀 레퍼런스 프로펠을 사용합니다.이것은 내가 가장 좋아하는 대안이다. 가장 간단한 대안, 리액트에서의 합법적인 방법, 그리고 필요하지 않다.forwardRef.
const Comp3 = <T extends Option>(props: Props<T> & {myRef: Ref<HTMLDivElement>})
=> <div ref={myRef}> {props.options.map(o => <p>{o.label}</p>)} </div>
const Usage3 = () => <Comp3 options={options} myRef={myRef} />
4. 글로벌 타입의 증강을 사용한다.
다음 코드를 앱에 한 번 추가하면 다른 모듈에 추가할 수 있습니다.react-augment.d.ts:
import React from "react"
declare module "react" {
function forwardRef<T, P = {}>(
render: (props: P, ref: ForwardedRef<T>) => ReactElement | null
): (props: P & RefAttributes<T>) => ReactElement | null
}
그러면 React 모듈 유형 선언, 재정의가 증가합니다.forwardRef새로운 함수 오버로드 타입 시그니처를 사용합니다.트레이드오프: 컴포넌트 속성displayName이제 활자 어설션이 필요합니다.
1 왜 원래 케이스가 작동하지 않는 거죠?
React.forwardRef 에는 다음 유형이 있습니다.
function forwardRef<T, P = {}>(render: ForwardRefRenderFunction<T, P>):
ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<T>>;
따라서 이 함수는 일반적인 컴포넌트와 같은 렌더 함수를 사용합니다. ForwardRefRenderFunction타입이 지정된 최종 컴포넌트를 반환한다.ForwardRefExoticComponent이 두 가지는 추가 속성을 가진 함수 유형 선언일 뿐입니다. displayName,defaultProps기타.
현재 TypeScript 3.4 기능은 Higher-Rank Types와 유사한 고차 함수 유형 추론이라고 합니다.기본적으로 프리타입 파라미터(입력함수의 범용)를 외부 호출함수에 전파할 수 있습니다.React.forwardRef여기서 - 결과 함수 구성요소는 여전히 일반적입니다.
그러나 이 기능은 [1], [2]에서 설명한 것처럼 일반 함수 유형에서만 사용할 수 있습니다.
소스 타입과 타깃타입이 모두 순수한 함수타입인 경우, 즉 단일 콜시그니처가 있고 다른 멤버가 없는 타입일 경우에만 상위 함수타입 추론을 합니다.
은 의위 above above above above above above 가 됩니다.React.forwardRef츠키다
이 블로그 투고를 읽고 이 질문을 발견했는데, 현재 받아들여지고 있는 답변보다 더 간단한 방법이 있다고 생각합니다.
먼저 타입 스크립트로 콜시그니처라고 불리는 것을 사용하여 컴포넌트의 유형을 유지하는 인터페이스를 정의합니다.
interface WithForwardRefType extends React.FC<WithForwardRefProps<Option>> {
<T extends Option>(props: WithForwardRefProps<T>): ReturnType<React.FC<WithForwardRefProps<T>>>
}
함수 시그니처 자체가 인터페이스가 아닌 범용으로 선언되는 것에 주의해 주십시오.이것이 이 기능을 실현하기 위한 열쇠입니다.반응하다하여 FC의 한 컴포넌트 합니다.displayName,defaultProps 등등.
다음으로 인터페이스를 컴포넌트 유형으로 제공하고 소품 유형을 지정할 필요 없이 컴포넌트를 다음 컴포넌트에 전달할 수 있습니다.forwardRef~하다
export const WithForwardRef: WithForwardRefType = forwardRef((
props,
ref?: React.Ref<HTMLDivElement>,
) => {
const { options, onChange } = props;
return (
<div ref={ref}>
{options.map((opt) => {
return (
<div
onClick={() => {
onChange(opt);
}}
>
{opt.label}
</div>
);
})}
</div>
);
});
여기 Sandbox 링크
참고 자료:
언급URL : https://stackoverflow.com/questions/58469229/react-with-typescript-generics-while-using-react-forwardref
'source' 카테고리의 다른 글
| 팬더에 JSON이 두 개 이상 포함된 파일 로드 (0) | 2023.03.16 |
|---|---|
| 스프링 부트 응용 프로그램의 메인 클래스를 테스트하는 방법 (0) | 2023.03.16 |
| 공급자가 Oracle 클라이언트 버전과 호환되지 않습니다. (0) | 2023.03.16 |
| WooCommerce에서 다운로드 가능한 제품 기능을 비활성화하는 방법 (0) | 2023.03.16 |
| Java Spring Boot Test: 테스트 컨텍스트에서 Java 컨피규레이션클래스를 제외하는 방법 (0) | 2023.03.16 |