TypeScript 및 React-어린이 유형?


138

다음과 같이 매우 간단한 기능 구성 요소가 있습니다.

import * as React from 'react';

export interface AuxProps  { 
    children: React.ReactNode
 }


const aux = (props: AuxProps) => props.children;

export default aux;

그리고 또 다른 구성 요소 :

import * as React from "react";

export interface LayoutProps  { 
   children: React.ReactNode
}

const layout = (props: LayoutProps) => (
    <Aux>
        <div>Toolbar, SideDrawer, Backdrop</div>
        <main>
            {props.children}
        </main>
    <Aux/>
);

export default layout;

다음과 같은 오류가 계속 발생합니다.

[ts] JSX 요소 유형 'ReactNode'는 JSX 요소에 대한 생성자 함수가 아닙니다. 'undefined'유형은 'ElementClass'유형에 할당 할 수 없습니다. [2605]

올바르게 입력하려면 어떻게합니까?

답변:


133

다만 children: React.ReactNode


1
이것은 여기에서 정답입니다! JSX.Element유효한 React 자식은 문자열, 부울, null 일 수 있기 때문에 충분하지 않습니다 ReactChild. 같은 이유로 인해 불완전합니다
Pierre Ferry

2
@PierreFerry 문제는 거의 모든 것이에 할당 될 수 있다는 것 ReactNode입니다. 다음과 children같이 입력하는 것과 유사한 유형 안전성 측면에서 도움이되지 않습니다 . 설명 any은 내 대답 을 참조하십시오 .
ford04

@ ford04로 응답 해 주셔서 감사합니다. 내 사용 사례에서 나는 아이들이 느슨하게 타이핑되기를 원합니다. 내 구성 요소는 모든 종류의 유효한 React 자식을 허용합니다. 그래서 나는 이것이 내가 찾던 답이라고 믿는다 :)
Pierre Ferry

47

<Aux>JSX에서 사용하려면 을 반환하는 함수 여야합니다 ReactElement<any> | null. 이것이 함수 컴포넌트 의 정의입니다 .

그러나 현재 React.ReactNode는 훨씬 더 넓은 유형 인를 반환하는 함수로 정의되어 있습니다. React 타이핑은 다음과 같이 말합니다.

type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;

반환 된 값을 React Fragment ( <></>) 에 래핑하여 원하지 않는 유형이 중화되었는지 확인합니다 .

const aux: React.FC<AuxProps> = props =>
  <>{props.children}</>;

childrenReact Fragment 로 래핑해야하는 이유를 이해할 수 없습니다 . 설명할까요? React에서는 return children;.
sanfilippopablo 19

1
children배열 이면 아닙니다 . 이 경우 단일 노드로 래핑하거나 React Fragments를 사용해야합니다.
Karol Majewski

예, 내 코드에는 다음 return React.Children.count(children) > 1 ? <>{children}</> : children이 있지만 typescript는 그것에 대해 불평합니다. 나는 그것을 단지 <>{children}</>.
sanfilippopablo 19

2
children하나의 항목 만 포함하는 요소 목록 이기 때문에 불평 합니다. 나는 당신이 return React.Children.count(children) > 1 ? <>{children}</> : children[0]@sanfilippopablo를 했다면 작동 할 것이라고 생각합니다
tamj0rd2

이것은 최신 버전의 React에서 작동하지 않는 것 같습니다. 콘솔에 로그인하여 어린이 소품이 있음을 확인할 수 있지만 <React.Fragment>주변에 있어도 {props.children}아무것도 반환하지 않습니다.
Mark

34

이것은 나를 위해 일한 것입니다.

interface Props {
  children: JSX.Element[] | JSX.Element
}

편집children: React.ReactNode 대신 지금 사용 하는 것이 좋습니다 .


8
그것은 정의의 범위가 충분하지 않습니다. 자식은 문자열이 될 수 있습니다.
Mike S

내 구성 요소가 하나 이상의 JSX.Elements를 예상했기 때문에 적어도이 예제는 나를 위해 일했습니다. 감사!
Italo Borges

1
이것은 JavaScript 표현식에서 자식으로 작동하지 않습니다 <MyComponent>{ condition ? <span>test</span> : null}</MyComponent>. 사용 children: ReactNode하면 작동합니다.
Nickofthyme

10

다음과 같이 구성 요소를 선언 할 수 있습니다.

const MyComponent: React.FunctionComponent = (props) => {
    return props.children;
}

9

ReactChildrenReactChild다음을 사용할 수 있습니다 .

import React, { ReactChildren, ReactChild } from 'react';

interface AuxProps {
  children: ReactChild | ReactChildren;
}

const Aux = ({ children }: AuxProps) => (<div>{children}</div>);

export default Aux;

6

TypeScript 사이트에서 : https://github.com/Microsoft/TypeScript/issues/6471

권장되는 방법은 소품 유형을 {children ?: any}로 작성하는 것입니다.

그것은 나를 위해 일했습니다. 자식 노드는 여러 가지가 될 수 있으므로 명시 적 타이핑은 대소 문자를 놓칠 수 있습니다.

https://github.com/Microsoft/TypeScript/issues/13618 에서 후속 문제에 대한 더 긴 논의가 있지만 모든 접근 방식은 여전히 ​​작동합니다.


6

함수 구성 요소 반환 유형은 JSXElement | nullTypeScript 로 제한됩니다 . 이것은 현재 유형 제한이며 순수한 React 는 더 많은 것을 허용합니다. 반환 유형을 합니다.

최소 데모 스 니펫

해결 방법으로 유형 어설 션 또는 조각을 사용할 수 있습니다.

const Aux = (props: AuxProps) => <>props.children</>; 
const Aux2 = (props: AuxProps) => props.children as ReactElement; 

ReactNode

children: React.ReactNode에 대한 강력한 유형을 갖는 것이 목표 인 경우 차선책 일 수 있습니다 Aux.

거의 모든 것을 현재 ReactNode유형에 할당 할 수 있습니다 {} | undefined | null. 케이스에 대한 더 안전한 유형은 다음과 같습니다.

interface AuxProps {
  children: ReactElement | ReactElement[]
}

예:

을 감안할 Aux필요는 요소 반작용 children, 우리가 실수로 추가 string그것입니다. 그런 다음 위의 솔루션 은 이와 대조적으로 오류가 발생 ReactNode합니다. 연결된 놀이터를 살펴보십시오.

Typed childrenRender Prop 콜백 과 같은 비 JSX props에도 유용합니다 .


5

를 사용할 수도 있습니다 React.PropsWithChildren<P>.

type ComponentWithChildProps = React.PropsWithChildren<{example?: string}>;

3

일반적으로 모든 종류의를 찾을 수있는 방법은 예입니다. typescript의 장점은 올바른 파일 이있는 한 모든 유형에 액세스 할 수 있다는 것 @types/입니다.

이 질문에 직접 답하기 위해 저는 children소품 이있는 컴포넌트 리 액트 사용을 생각했습니다 . 가장 먼저 떠오른 것은? 어때요 <div />?

당신이 할 필요가 열려 vscode 새로운 만들 .tsxA가 함께 프로젝트 반응에 파일을 @types/react.

import React from 'react';

export default () => (
  <div children={'test'} />
);

children소품 위로 마우스를 가져 가면 유형이 표시됩니다. 그리고 당신은 무엇을 알고 있습니까-그 유형은 ReactNode(필요 없음 ReactNode[])입니다.

여기에 이미지 설명 입력

그런 다음 유형 정의를 클릭하면 인터페이스 children에서 오는 정의로 바로 이동합니다 DOMAttributes.

// node_modules/@types/react/index.d.ts
interface DOMAttributes<T> {
  children?: ReactNode;
  ...
}

참고 :이 프로세스는 알 수없는 유형을 찾는 데 사용해야합니다! 그들 모두는 당신이 그들을 찾기를 기다리고 있습니다 :)


2

어린이를 포함하는 유형으로 다음을 사용하고 있습니다.

type ChildrenContainer = Pick<JSX.IntrinsicElements["div"], "children">

이 자식 컨테이너 유형은 모든 다른 경우를 지원하기에 충분히 일반적이며 ReactJS API 와도 일치합니다.

따라서 예를 들어 다음과 같습니다.

const layout = ({ children }: ChildrenContainer) => (
    <Aux>
        <div>Toolbar, SideDrawer, Backdrop</div>
        <main>
            {children}
        </main>
    <Aux/>
)

1

이러한 답변은 구식 인 것으로 보입니다. 이제 React에는 기본 제공 유형이 PropsWithChildren<{}>있습니다. 이 페이지의 일부 정답과 유사하게 정의됩니다.

type PropsWithChildren<P> = P & { children?: ReactNode };


1
P그 유형의 경우는 무엇입니까 ?
sunpietro

P구성 요소의 소품 유형입니다
Tim Iles

-2

React 컴포넌트는 단일 래퍼 노드를 가지고 있거나 노드 배열을 반환해야합니다.

귀하의 <Aux>...</Aux>구성 요소는 두 개의 노드가 divmain.

자녀를 divin Aux구성 요소 로 감싸십시오 .

import * as React from 'react';

export interface AuxProps  { 
  children: React.ReactNode
}

const aux = (props: AuxProps) => (<div>{props.children}</div>);

export default aux;

1
사실이 아니다. React 16+에서는 더 이상 그렇지 않습니다.
Andrew Li
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.