Як користуватися дітьми з функціональним компонентом React Stateless у TypeScript?


85

Використовуючи TypeScript з React, нам більше не потрібно розширювати, React.Propsщоб компілятор знав, що всі компоненти реагуючих компонентів можуть мати дітей:

interface MyProps { }

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

Однак, схоже, це не стосується функціональних компонентів без громадянства:

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

Видає помилку компіляції:

Помилка: (102, 17) TS2339: Властивість "діти" не існує для типу "MyProps".

Я думаю, це тому, що компілятору насправді немає можливості дізнатися, що childrenу аргументі props буде вказана функція ванілі .

Тож питання полягає в тому, як ми повинні використовувати дітей у функціональному компоненті без стану у TypeScript?

Я міг би повернутися до колишнього способу MyProps extends React.Props, але Propsінтерфейс позначений як застарілий , а компоненти без громадянства не мають або підтримують, Props.refяк я розумію.

Тож я міг визначити childrenреквізит вручну:

interface MyProps {
  children?: React.ReactNode;
}

По-перше: це ReactNodeправильний тип?

По-друге: я повинен писати діти як необов’язкові ( ?), інакше споживачі вважатимуть, що childrenце атрибут компонента ( <MyStatelessComponent children={} />), і викликатиме помилку, якщо не буде вказано значення.

Здається, мені чогось не вистачає. Хтось може пояснити, чи мій останній приклад - це спосіб використання функціональних компонентів без громадянства з дітьми в React?

Відповіді:


82

Оновлення React 16.8: Із React 16.8 імена React.SFCта React.StatelessComponentзастаріли. Власне, вони стали псевдонімами для React.FunctionComponentтипу або React.FCкоротко.

Ви використовували б їх однаково, хоча:

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

До React 16.8 (Старіші):

На даний момент ви можете використовувати React.StatelessComponent<>тип, як:

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

Що я додав, це встановлення типу повернення компонента React.StatelessComponentтипу.

Для компонента з вашим власним власним реквізитом (наприклад, MyPropsінтерфейсом):

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

Тепер propsмає childrenвластивість, а також властивості MyPropsінтерфейсу.

Я перевірив це у версії машинопису 2.0.7

Крім того, ви можете використовувати React.SFCзамість React.StatelessComponentкороткості.


Дякую! Здається, я на старій версії типізації, яка цього не підтримує ... Думаю, настав час кусати кулю і використовувати TS 2.0 з@types
Аарон Білл

2
React.StatelessComponent/ React.SFCзастаріли. Рекомендується посилатися React.FunctionComponentзамість цього.
Олександр Качкаєв

Зауважте, що цей метод не працює, якщо у вас є загальний компонент
FunkeyFlo

93

Ви можете використовувати React.PropsWithChildren<P>тип для вашого реквізиту:

interface MyProps { }

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


0

Більш проста відповідь: Використовуйте ReactNode:

interface MyProps {
  children?: React.ReactNode
}

Якщо childrenце необов’язково чи ні (тобто мати ?чи ні), залежить від вашого компонента. Це ?найкоротший спосіб висловити це, тому в цьому немає нічого поганого.

Про історію: Це не обов’язково була правильна відповідь, коли його спочатку запитували: тип ReactNodeбув доданий у (майже) поточній формі в березні 2017 року лише цим запитом на витягування , але майже кожен, хто читає це сьогодні, повинен бути на досить сучасній версії React .

Нарешті, про передачу childrenяк "атрибут" (що, в мові React, буде передавати його як "prop", а не атрибут): Це можливо, але в більшості випадків читається краще при передачі JSX дочірніх:

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

читає легше, ніж

<MyComponent children={<p>This is part of the children.</p>} />
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.