TypeScript ve React - çocuklar yazıyor mu?


140

Aşağıdaki gibi çok basit bir işlevsel bileşene sahibim:

import * as React from 'react';

export interface AuxProps  { 
    children: React.ReactNode
 }


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

export default aux;

Ve başka bir bileşen:

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;

Şu hatayı almaya devam ediyorum:

[ts] JSX öğe türü 'ReactNode', JSX öğeleri için bir yapıcı işlevi değildir. 'Undefined' türü 'ElementClass' türüne atanamaz. [2605]

Bunu nasıl doğru yazabilirim?

Yanıtlar:


134

Sadece children: React.ReactNode


1
Burada doğru cevap budur! JSX.Elementgeçerli bir React çocuğu bir string, boolean, null olabileceği için yeterince iyi değil ... ReactChildaynı nedenlerle de eksik
Pierre Ferry

2
@PierreFerry Sorun şu ki, hemen hemen her şeye atanabilir ReactNode. Yazarak benzer tip güvenliği açısından yardıma değil childrenolarak any- benim bkz cevabı bir açıklama.
ford04

Cevabınız için teşekkürler @ ford04. Benim kullanım durumumda çocukların gevşek yazmasını istiyorum. Bileşenim her türlü geçerli React çocuğunu kabul ediyor. Bu yüzden hala aradığım yanıtın bu olduğuna inanıyorum :)
Pierre Ferry

47

<Aux>JSX'inizde kullanmak için geri dönen bir fonksiyon olması gerekir ReactElement<any> | null. Bu, bir fonksiyon bileşeninin tanımıdır .

Ancak, şu anda React.ReactNodeçok daha geniş bir tür olan geri dönen bir işlev olarak tanımlanmaktadır . React yazılarının dediği gibi:

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

Döndürülen değeri React Fragment ( <></>) içine sararak istenmeyen türlerin etkisiz hale getirildiğinden emin olun :

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

Neden childrenbir React Fragmentine sarılması gerektiğini anlamıyorum . Açıklamak ister misin? React'te tam anlamıyla geçerli return children;.
sanfilippopablo

1
Değil ise childrenbir dizi vardır. Eğer durum buysa, onları tek bir düğüme bağlamanız veya React Fragments kullanmanız gerekir.
Karol Majewski

Evet, return React.Children.count(children) > 1 ? <>{children}</> : childrenkodumda var:, ama daktilo bundan şikayet ediyor. Ben onu sadece ile değiştirdim <>{children}</>.
sanfilippopablo

2
childrenSadece 1 öğe içeren bir öğe listesi olduğu için şikayet ediyor. return React.Children.count(children) > 1 ? <>{children}</> : children[0]@Sanfilippopablo yapsaydın işe yarayacağını düşünüyorum
tamj0rd2

Bu, React'in daha yeni sürümlerinde işe yaramıyor gibi görünüyor. Ben konsol açmış ve bir çocuk pervane var ama bile teyit edebiliriz <React.Fragment>çevreleyen {props.children}bir şey dönen değilim.
Mark

34

Bu benim için çalıştı:

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

Düzenle Onun children: React.ReactNodeyerine şimdi kullanmanızı tavsiye ederim .


8
Bu yeterince geniş bir tanım değil. Çocuk bir dizge olabilir.
Mike S

En azından bu örnek benim için çalıştı çünkü bileşenimin 1 veya daha fazla JSX.Elements beklemesi gerekiyordu. Teşekkürler!
Italo Borges

1
Bu, alt öğeler olarak JavaScript ifadelerinde çalışmayacaktır <MyComponent>{ condition ? <span>test</span> : null}</MyComponent>. Kullanmak children: ReactNodeişe yarayacak.
Nickofthyme

10

Bileşeninizi şu şekilde ilan edebilirsiniz:

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

9

Sen kullanabilirsiniz ReactChildrenve ReactChild:

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

interface AuxProps {
  children: ReactChild | ReactChildren;
}

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

export default Aux;


6

İşlev bileşeni dönüş türü, JSXElement | nullTypeScript ile sınırlıdır . Bu bir akım türü sınırlamasıdır, saf React daha fazla dönüş türüne izin verir .

Minimal gösteri pasajı

Geçici çözüm olarak bir tür iddiası veya Parçalar kullanabilirsiniz:

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

ReactNode

children: React.ReactNodehedef güçlü türlere sahip olmaksa yetersiz olabilir Aux.

Hemen hemen her şey ReactNode, eşdeğer olan geçerli türe atanabilir {} | undefined | null. Vakanız için daha güvenli bir tür şunlar olabilir:

interface AuxProps {
  children: ReactElement | ReactElement[]
}

Misal:

Verilen Auxihtiyaçlar için React elementleri gibi children, yanlışlıkla stringona bir ekledik . O zaman yukarıdaki çözüm , tersine hata verecektir ReactNode- bağlantılı oyun alanlarına bir göz atın.

Yazılan childrenbir gibi non-JSX sahne için yararlı olan Prop oluşturulma geri arama.


5

Ayrıca kullanabilirsiniz React.PropsWithChildren<P>.

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

3

Genel türlü bulmak için bir yol örneğin gereğidir. Daktilo etmenin güzelliği , doğru dosyalara sahip olduğunuz sürece tüm türlere erişiminizin olmasıdır @types/.

Bunu kendim yanıtlamak için, childrenpervaneye sahip bir bileşen tepkimenin kullanımlarını düşündüm . Akla gelen ilk şey? Nasıl bir <div />?

Tek yapmanız gereken, vscode'u açmak ve .tsxbir react projesinde @types/react.

import React from 'react';

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

Pervanenin üzerine gelmek childrensize türü gösterir. Ve ne biliyorsun - Tipi ReactNode(gerek yok ReactNode[]).

görüntü açıklamasını buraya girin

Daha sonra tip tanımına tıklarsanız, sizi doğrudan arayüzden childrengelme tanımına getirir DOMAttributes.

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

Not: Bu işlem, herhangi bir bilinmeyen türü bulmak için kullanılmalıdır! Hepsi orada, onları bulmanı bekliyor :)


2

Çocuk içeren bir tür olarak kullanıyorum:

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

Bu alt kapsayıcı türü, tüm farklı durumları destekleyecek kadar geneldir ve ayrıca ReactJS API ile uyumludur.

Yani, örneğiniz için şöyle bir şey olabilir:

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

1

Bu cevapların modası geçmiş gibi görünüyor - React artık yerleşik bir türe sahip PropsWithChildren<{}>. Bu sayfadaki bazı doğru cevaplara benzer şekilde tanımlanmıştır:

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


1
PBu tür durumunda ne var ?
sunpietro

Pbileşeninizin aksesuarlarının türüdür
Tim Iles

-2

React bileşenleri tek bir sarmalayıcı düğüme sahip olmalı veya bir düğüm dizisi döndürmelidir.

Kişisel <Aux>...</Aux>bileşen iki düğüme sahiptir divvemain .

Bir çocuklarınızı sarmak için deneyin diviçinde Auxbileşen.

import * as React from 'react';

export interface AuxProps  { 
  children: React.ReactNode
}

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

export default aux;

1
Doğru değil. React 16 + 'da artık durum böyle değil, artı durum böyle olsaydı hata bunu söylerdi
Andrew Li
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.