Jak używać dzieci z bezstanowym komponentem funkcyjnym React w TypeScript?


85

Używając TypeScript z Reactem, nie musimy już rozszerzać React.Props, aby kompilator wiedział, że wszystkie właściwości komponentów reagujących mogą mieć dzieci:

interface MyProps { }

class MyComponent extends React.Component<MyProps, {}> {
  public render(): JSX.Element {
    return <div>{this.props.children}</div>;
  }
}

Jednak wydaje się, że nie ma to miejsca w przypadku bezstanowych komponentów funkcjonalnych:

const MyStatelessComponent = (props: MyProps) => {
  return (
    <div>{props.children}</div>
  );
};

Emituje błąd kompilacji:

Błąd: (102, 17) TS2339: Właściwość „dzieci” nie istnieje w typie „MyProps”.

Wydaje mi się, że dzieje się tak, ponieważ kompilator naprawdę nie może wiedzieć, że childrenw argumencie props zostanie podana funkcja waniliowa .

Zatem pytanie brzmi, jak powinniśmy używać dzieci w bezstanowych składnikach funkcjonalnych w TypeScript?

Mógłbym wrócić do starego sposobu MyProps extends React.Props, ale Propsinterfejs jest oznaczony jako przestarzały , a składniki bezstanowe nie mają ani nie obsługują, Props.refjak rozumiem.

Mogłem więc childrenręcznie zdefiniować rekwizyt:

interface MyProps {
  children?: React.ReactNode;
}

Po pierwsze: czy jest ReactNodeto właściwy typ?

Po drugie: muszę napisać dzieci jako opcjonalne ( ?), inaczej konsumenci pomyślą, że childrenma to być atrybut komponentu ( <MyStatelessComponent children={} />) i zgłoszą błąd, jeśli nie otrzymają wartości.

Wygląda na to, że czegoś mi brakuje. Czy ktoś może wyjaśnić, czy moim ostatnim przykładem jest sposób używania bezpaństwowych komponentów funkcjonalnych z dziećmi w Reakcie?

Odpowiedzi:


82

Aktualizacja React 16.8: Od React 16.8 nazwy React.SFCi React.StatelessComponentsą przestarzałe. Właściwie stały się aliasami React.FunctionComponenttypu lub React.FCw skrócie.

Używałbyś ich jednak w ten sam sposób:

const MyStatelessComponent : React.FunctionComponent<MyProps> = props =>
    <div>
        <p>{props.propInMyProps}</p>
        <p>{props.children}</p>
    </div>

Przed React 16.8 (starsze):

Na razie możesz użyć React.StatelessComponent<>typu jako:

const MyStatelessComponent : React.StatelessComponent<{}> = props =>
    <div>{props.children}</div>

Dodałem tam ustawienie zwracanego typu komponentu na React.StatelessComponenttyp.

W przypadku komponentu z własnymi niestandardowymi właściwościami (takimi jak MyPropsinterfejs):

const MyStatelessComponent : React.StatelessComponent<MyProps> = props =>
    <div>
        <p>{props.propInMyProps}</p>
        <p>{props.children}</p>
    </div>

Teraz propsma childrenwłaściwość jak i te z MyPropsinterfejsu.

Sprawdziłem to w maszynopisie w wersji 2.0.7

Dodatkowo możesz użyć React.SFCzamiast React.StatelessComponentdla zwięzłości.


Dzięki! Wygląda na to, że jestem na starej wersji typografii, która tego nie obsługuje ... Myślę, że nadszedł czas, aby ugryźć kulę i użyć TS 2.0 z@types
Aaronem Beallem

2
React.StatelessComponent/ React.SFCsą przestarzałe. React.FunctionComponentZamiast tego zaleca się odwołanie .
Alexander Kachkaev

Zauważ, że ta metoda nie działa, jeśli masz komponent ogólny
FunkeyFlo,

93

Możesz użyć React.PropsWithChildren<P>typu dla swoich rekwizytów:

interface MyProps { }

function MyComponent(props: React.PropsWithChildren<MyProps>) {
  return <div>{props.children}</div>;
}

0

Możesz użyć

interface YourProps { }
const yourComponent: React.SFC<YourProps> = props => {}

0

Prostsza odpowiedź: użyj ReactNode:

interface MyProps {
  children?: React.ReactNode
}

Jeśli childrennie jest obowiązkowe, czy nie (czyli posiadające ?lub nie) zależy od komponentu. Jest ?to najbardziej zwięzły sposób wyrażenia tego, więc nie ma w tym nic złego.

O historii: To niekoniecznie była prawidłowa odpowiedź, gdy pierwotnie zapytano: Typ ReactNodezostał dodany (prawie) w swojej obecnej formie w marcu 2017 r. Tylko przez to żądanie ściągnięcia , ale prawie wszyscy czytający to dzisiaj powinni korzystać z wystarczająco nowoczesnej wersji React .

Na koniec, o przekazywaniu childrenjako „atrybut” (co w języku React oznaczałoby przekazywanie go jako „prop”, a nie atrybut): Jest to możliwe, ale w większości przypadków czyta się lepiej, gdy przekazuje się dzieciom JSX:

<MyComponent>
  <p>This is part of the children.</p>
</MyComponent>

czyta łatwiej niż

<MyComponent children={<p>This is part of the children.</p>} />
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.