본문 바로가기

개발하자

React with TypeScript를 사용하여 어린이를 특정 구성 요소로 제한할 수 있습니까?

반응형

React with TypeScript를 사용하여 어린이를 특정 구성 요소로 제한할 수 있습니까?

React with TypeScript를 사용하여 설정 또는 확장과 같이 의 유형을 정의하는 여러 가지 방법이 있습니다. 그러나 그렇게 하면 React 하위 요소가 될 수 있는 특정 요소를 추가로 제한할 수 있습니까?

function ListItem() {
  return (
    <li>A list item<li>
  );
}

//--------------------

interface ListProps {
  children: React.ReactChild | React.ReactChild[]
}

function List(props: ListProps) {
  return (
    <ul>
      {props.children} // what if I only want to allow elements of type ListItem here?
    </ul>
  );
}

위의 시나리오가 주어지면 유형의 자식만 허용하는 방식으로 설정할 수 있습니까? 다음과 유사한 코드(잘못된 코드:

interface ListProps {
  children: React.ReactChild<ListItem> | React.ReactChild<ListItem>[]
}



여기 여러 단계가 있는 "마법사"에 사용하는 간단한 예가 있습니다. 주 구성 요소인 WizardStep(복수)과 하위 구성 요소인 WizardStep(단수)을 사용하며, 이 속성은 주 구성 요소인 WizardStep(단수)에서 렌더링됩니다. 이 작업을 올바르게 수행하기 위한 핵심은 Children.map(...) 호출입니다. 이 호출은 React가 "Children"을 배열로 처리하고 Typescript와 IDE가 올바르게 작동하도록 합니다.

const WizardSteps: FunctionComponent<WizardStepsProps> & WizardSubComponents = ({children}) => {
    const steps = Children.map(children, child => child); /* Treat as array with requisite type */

    return (
        <div className="WizardSteps">
            <header>
                <!-- Note the use of step.props.label, which is properly typecast -->
                {steps.map(step => <div className="WizardSteps__step">{step.props.label}</div>)}
            </header>
            <main>
                <!-- Here you can render the body of each WizardStep child component -->
                {steps.map(step => <div className="WizardSteps__body">{step}</div>)}
            </main>
        </div>
    );
}

const Step: FunctionComponent<WizardStepProp> = ({label, onClick}) => {
    return <span className="WizardSteps__label">
        {label}
    </span>
}

WizardSteps.Step = Step;

type WizardSubComponents = {
    Step: FunctionComponent<WizardStepProp>
}

type WizardStepsProps = {
    children: ReactElement<WizardStepProp> | Array<ReactElement<WizardStepProp>>
};

type WizardStepProp = {
    label: string
    onClick?: string
    children?: ReactNode
}



그렇고 말고요. 적절한 제네릭을 위해 사용하면 됩니다.

interface ListItemProps {
   text: string
}

interface ListProps {
   children: React.ReactElement<ListItemProps> | React.ReactElement<ListItemProps>[];
}

편집 - 코드 샌드박스의 예를 만들었습니다.

https://codesandbox.io/s/hardcore-cannon-16kjo?file=/src/App.tsx




당신은 이렇게 반응하는 아이들을 억제할 수 없습니다.

반응 기능 구성 요소는 특정 소품 유형을 가지고 반환되는 기능일 뿐입니다. 즉, 하위 항목을 전달하기 전에 구성 요소를 전달하면 반응은 해당 JSX가 생성한 내용을 전혀 알지 못하고 그대로 전달합니다.

문제는 구성 요소를 구문으로 렌더링한다는 것입니다. 그 이후에는 JSX 노드의 일반 트리에 불과합니다.


하지만, 이것은 약간 와 같이 들린다. 일반적으로 이것이 필요한 경우 API를 설계하는 더 나은 방법이 있습니다.

대신, 당신은 소품으로 전달될 객체들의 배열을 구성 요소 안으로 가져가는 것을 만들고 지지할 수 있다.

예:

function ListItem({ children }: { children: React.ReactNode }) {
  return (
    <li>{children}</li>
  );
}

function List(props: { items: string[] }) {
  return (
    <ul>
      {props.items.map((item) => <ListItem>{item}</ListItem> )}
    </ul>
  );
}

const good = <List items={['a', 'b', 'c']} />

이 예에서는 소품을 타이핑하는 데 불과하며, 자신의 자식들을 생성하는 방법을 알고 있습니다.

놀이터.


반응형