소품을 유지하면서 React 및 TypeScript HTML 요소 확장
난 이걸 이해할 수가 없어. 아마 6번 정도 시도했고 항상 의지했어.any
HTML 요소로 시작하여 컴포넌트로 랩하고 HTML 소품이 모든 것을 통과하도록 다른 컴포넌트로 랩하는 합법적인 방법이 있습니까?HTML 요소를 기본적으로 맞춤화하시겠습니까?예를 들어 다음과 같습니다.
interface MyButtonProps extends React.HTMLProps<HTMLButtonElement> {}
class MyButton extends React.Component<MyButtonProps, {}> {
render() {
return <button/>;
}
}
interface MyAwesomeButtonProps extends MyButtonProps {}
class MyAwesomeButton extends React.Component<MyAwesomeButtonProps, {}> {
render() {
return <MyButton/>;
}
}
사용방법:
<MyAwesomeButton onClick={...}/>
이런 종류의 구성을 시도할 때마다 다음과 같은 오류가 발생합니다.
foo의 속성 'ref'를 대상 속성에 할당할 수 없습니다.
컴포넌트의 정의를 변경하여 리액트 html 버튼 소품을 사용할 수 있습니다.
class MyButton extends React.Component<MyButtonProps & React.HTMLProps<HTMLButtonElement>, {}> {
render() {
return <button {...this.props}/>;
}
}
그러면 'MyButtonProps'와 함께 버튼 소품을 입력하려는 것을 타이프스크립트 컴파일러에 알립니다.
저는 항상 이런 식으로 하고 싶어요.
import React from 'react';
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
title: string;
showIcon: boolean;
}
const Button: React.FC<ButtonProps> = ({ title, showIcon, ...props }) => {
return (
<button {...props}>
{title}
{showIcon && <Icon/>}
</button>
);
};
다음 작업을 수행할 수 있습니다.
<Button
title="Click me"
onClick={() => {}} {/* You have access to the <button/> props */}
/>
위의 답변은 시대에 뒤떨어진 것 같습니다.
제 경우 스타일링된 컴포넌트를 기능 컴포넌트로 래핑하고 있지만 일반 HTML 버튼 속성을 표시하고 싶습니다.
export const Button: React.FC<ButtonProps &
React.HTMLProps<HTMLButtonElement>> = ({
children,
icon,
...props,
}) => (
<StyledButton {...props}>
{icon && <i className="material-icons">{icon}</i>}
{children}
</StyledButton>
);
네이티브 요소를 확장할 때는 다음과 같이 합니다.
import React, { ButtonHTMLAttributes, forwardRef } from "react";
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
myExtraProp1: string;
myExtraProp2: string;
}
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
({ myExtraProp1, myExtraProp2, ...props }, ref) => (
<button
{...props}
ref={ref}
// Do something with the extra props
/>
),
);
Button.displayName = "Button";
forwardRef
를 사용하여 기본 HTML 요소에 대한 참조를 얻을 수 있습니다.ref
컴포넌트 사용 시.
이것은, 인터페이스 대신에 다음의 타입을 사용해 동작했습니다.
type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {
children: React.ReactNode;
icon?: React.ReactNode;
};
function Button({ children, icon, ...props }: ButtonProps) {
return (
<button {...props}>
{icon && <i className="icon">{icon}</i>}
{children}
</button>
);
}
'@http/styled'의 스타일링된 컴포넌트를 사용하는 경우 어떤 답변도 작동하지 않습니다.
좀 더 깊이 들어가야 했어요.
import styled from "@emotion/styled";
import React, { ButtonHTMLAttributes } from 'react';
export type ButtonVariant = 'text' | 'filled' | 'outlined';
export const ButtonElement = styled.button`
display: flex;
align-items: center;
justify-content: center;
padding: 12px 16px;
`;
export interface ButtonProps {
variant: ButtonVariant;
}
export const Button: React.FC<ButtonProps & React.DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>> = ({
children,
variant,
...props
}) => (
<ButtonElement
{...props}
>
{children}
</ButtonElement>
);
이 스타일은 버튼의 모든 소품을 전달할 수 있으며, 그 외에도 패딩 {...props}을(를) ButtonElement로 쉽게 재사용하여 원하는 css 변경을 할 수 있습니다.
import { Button } from '@components/Button';
export const MySpecificButton = styled(Button)`
color: white;
background-color: green;
`;
import * as React from "react";
interface Props extends React.HTMLProps<HTMLInputElement> {
label?: string;
}
export default function FormFileComponent({ label, ...props }: Props) {
return (
<div>
<label htmlFor={props?.id}></label>
<input type="file" {...props} />
</div>
);
}
내가 이 코드를 풀면, 넌 그냥 가져오기만 하면 돼.ButtonHTMLAttributes
리액션으로부터, 그것으로 끝이다.
import { ButtonHTMLAttributes } from "react";
interface MyButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
children: any;
}
export const MyButton = (props: ButtonI) => {
const { children } = props;
return <button {...props}>{children}</button>;
};
인터페이스를 확장해야 합니다.
import {ButtonHTMLAttributes, ReactNode} from "react";
export interface ButtonProps extends DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>{
appearance: 'primary' | 'ghost';
children: ReactNode;
}
참조 키와 키를 사용하여 HTML 요소 확장
TL;DR
If you need to be able to accept `ref` and key then your type definition will need to use this long ugly thing:import React, { DetailedHTMLProps, HTMLAttributes} from 'react';
DetailedHTMLProps<HTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
유형 정의
Looking at the type definition file, this is the type. I'm not sure why it isn't shorter, it seems you always pass the same HTMLElement twice?type DetailedHTMLProps<E extends HTMLAttributes<T>, T> = ClassAttributes<T> & E;
상세 내용을 줄임HTML Props
독자적인 타입을 작성해, 델의 케이스에 맞추어 단축할 수 있습니다(일반적인 케이스인 것 같습니다).
import React, { ClassAttributes, HTMLAttributes} from 'react';
type HTMLProps<T> = ClassAttributes<T> & HTMLAttributes<T>;
export interface ButtonProps extends HTMLProps<HTMLButtonElement> {
variant: 'contained' | 'outlined';
}
샘플 컴포넌트
import React, {ClassAttributes, HTMLAttributes, ForwardedRef, forwardRef} from 'react';
type HTMLProps<T> = ClassAttributes<T> & HTMLAttributes<T>;
export interface ButtonProps extends HTMLProps<HTMLButtonElement> {
variant: 'contained' | 'outlined';
}
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
(props, ref) => {
return (
<button key="key is accepted" ref={ref} {...props}>
{props.children}
</button>
);
},
);
private yourMethod(event: React.MouseEvent<HTMLButtonElement>): void {
event.currentTarget.disabled = true;
}
<Button
onClick={(event) => this.yourMethod(event)}
/>
오늘 같은 문제가 발생했습니다.해결 방법은 다음과 같습니다.
ReactButtonProps.ts
import {
ButtonHTMLAttributes,
DetailedHTMLProps,
} from 'react';
/**
* React HTML "Button" element properties.
* Meant to be a helper when using custom buttons that should inherit native "<button>" properties.
*
* @example type MyButtonProps = {
* transparent?: boolean;
* } & ReactButtonProps;
*/
export type ReactButtonProps = DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>;
사용방법Button-ish
컴포넌트:
import classnames from 'classnames';
import React, { ReactNode } from 'react';
import { ReactButtonProps } from '../../types/react/ReactButtonProps';
type Props = {
children: ReactNode;
className?: string;
mode?: BtnMode;
transparent?: boolean;
} & ReactButtonProps;
const BtnCTA: React.FunctionComponent<Props> = (props: Props): JSX.Element => {
const { children, className, mode = 'primary' as BtnMode, transparent, ...rest } = props;
// Custom stuff with props
return (
<button
{...rest} // This forward all given props (e.g: onClick)
className={classnames('btn-cta', className)}
>
{children}
</button>
);
};
export default BtnCTA;
사용방법:
<BtnCTA className={'test'} onClick={() => console.log('click')}>
<FontAwesomeIcon icon="arrow-right" />
{modChatbot?.homeButtonLabel}
</BtnCTA>
사용할 수 있게 되었습니다.onClick
ReactButtonProps에서 확장되어 허용되며 이 기능은 자동으로 DOM으로 전송됩니다....rest
.
import { FC, HTMLProps } from 'react';
const Input: FC<HTMLProps<HTMLInputElement>> = (props) => {
return <input {...props} />;
};
이렇게 하면 단추 속성을 확장할 수 있습니다.
import { ButtonHTMLAttributes, ReactNode } from "react";
interface Props extends ButtonHTMLAttributes<HTMLButtonElement> {
children: ReactNode;
}
const Button = ({ children, ...props }: Props): JSX.Element => {
return <button {...props}>{children}</button>;
};
언급URL : https://stackoverflow.com/questions/40731352/extending-html-elements-in-react-and-typescript-while-preserving-props
'programing' 카테고리의 다른 글
AngularJS의 커스텀 디렉티브 *sure scope* 내에서 부모 스코프에 액세스하려면 어떻게 해야 합니까? (0) | 2023.02.28 |
---|---|
오류: 모듈 '@react-native-community/toolbar-android'를 확인할 수 없습니다. (0) | 2023.02.28 |
WooCommerce - calculate_shipping 기능으로 카트 아이템의 배송 클래스를 얻는 방법 (0) | 2023.02.28 |
WP_Query에서 날짜별로 주문하는 방법? (0) | 2023.02.28 |
mongoDB/mongoose: 늘이 아닌 경우 고유 (0) | 2023.02.23 |