Чистый компонент ReactJS TypeScript с дочерними элементами

У меня есть компонент TSX, который представляет собой контейнер, обертывающий своих дочерних элементов следующим образом:

import * as React from "react";

interface IProps extends React.Props<Box> {
}

interface IState {
}

export class Box extends React.Component<IProps, IState> {
    render() {
        return (
            <div>
                <h3>Check this out:</h3>
                {this.props.children}
            </div>);
    }
}

У меня также есть несколько чистых компонентов, например этот:

// ReSharper disable once InconsistentNaming - React components must start with a capital letter.
export function LabelTest(props: { label: string }) {
    return (
        <div style={{ display: "flex" }}>
            <label style={{ flex: "1 0 0" }}>{props.label}</label>
            <div style={{ width: "auto" }}>
                This is a pure component.
            </div>
        </div>);
}

Хотя я не могу понять, как создать чистый контейнерный компонент. Объявление выглядит нормально и не содержит ошибок:

// ReSharper disable once InconsistentNaming - React components must start with a capital letter.
export function LabelBox(props: { label: string, children: React.ReactNode }) {
  return (
    <div style={{ display: "flex" }}>
      <label style={{ flex: "1 0 0" }}>{props.label}</label>
      <div style={{ width: "auto" }}>
        {props.children}
      </div>
    </div>);
}

children это React.ReactNode, потому что это то, что находится в React.Props<X>.

При использовании я получаю TS2324 Свойство 'children' отсутствует в типе 'IntrinsicAttributes & {label: string; дети: ReactElement | строка | номер | {} | (Реак ....

// ReSharper disable once InconsistentNaming - React components must start with a capital letter.
export function LabelNumberInput(props: { label: string, value: number }) {
  return (
    <LabelBox label={props.label}>
      <input type="number" value={props.value} />
    </LabelBox>);
}

Я не могу сказать что-то вроде фрагмента ниже, потому что он скажет Не удается найти символ 'LabelBox' во внешнем модуле _.tsx (это файл, в котором находится весь этот код). Неважно, поставлю ли я на первое место функцию или интерфейс, но в целом это кажется неправильным.

interface ILabelBoxProps extends React.Props<LabelBox> { label: string }
export function LabelBox(props: ILabelBoxProps) {
  return (
    <div style={{ display: "flex" }}>
      <label style={{ flex: "1 0 0" }}>{props.label}</label>
      <div style={{ width: "auto" }}>
        {props.children}
      </div>
    </div>);
}

Как правильно создать компонент на чистом TypeScript React, способный принимать потомков, как это сделал бы компонент полного класса? Это возможно? Я не думаю, что этого не должно быть, это по-прежнему компонент без состояния, а children - это просто особый вид props, на самом деле настоящая проблема, похоже, заключается в инструментах (Visual Studio), которые не сопоставляют узел содержимого TSX с children опора.


person Tomáš Hübelbauer    schedule 14.06.2016    source источник


Ответы (2)


Как правильно сделать чистый компонент TypeScript React, способный принимать потомков, как это сделал бы компонент полного класса?

Образец ????:

interface PrimitiveProps extends React.HTMLProps<HTMLDivElement>{
   myAdditionalProp:any;
};

export const Content = (allProps: PrimitiveProps) => {
    const {myAdditionalProp, ...props} = allProps;
    return (
        <div data-comment="Content" {...props}/>;
    );
};

Конечно, вы можете делать что угодно с myAdditionalProp и, если хотите, добавить в PrimitiveProps дополнительные свойства. Только не забудьте удалить их из allProps перед тем, как пропустить через него. Обратите внимание, что children передается как часть allProps и, следовательно, props.

person basarat    schedule 15.06.2016
comment
Как ты это понял? Есть ли место, которое я должен был поискать, прежде чем задать вопрос, но я его пропустил? Запрос Google, о котором я не подумал? - person Tomáš Hübelbauer; 15.06.2016
comment
Опыт ¯\_(ツ)_/¯ ???? - person basarat; 15.06.2016
comment
Спасибо, что не держал это при себе, вы мне очень помогли! :) - person Tomáš Hübelbauer; 15.06.2016

Вот полный пример:

interface PaginationItemProps extends React.HTMLProps<HTMLDivElement> {
}

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

class Pagination extends React.Component<PaginationProps> {
  render() {
    return <div>          
        <PaginationItem>CHILDREN RENDER</PaginationItem>
    </div>
  }
}
person Shafqat Ali    schedule 09.03.2018