Как правильно набрать React.Children и React.cloneElement? - PullRequest
1 голос
/ 27 марта 2020

Я клонирую своих реагирующих детей с помощью cloneElement, но у меня возникают некоторые проблемы при их наборе.

Это мой код (он просто передает пользовательскую функцию onClick в качестве опоры детям):

const childrenWithProps = React.Children.map(children, child =>
  React.cloneElement(child as ReactChild, {
    onClick: (e: React.FormEvent) =>
      childrenClickHandler(
        e,
        child.props.children,
        onItemClick && onItemClick(e),
      ),
  }),
);

А это мой ReactChild тип:

export type ChildProps = {
  onClick?: (e?: React.ChangeEvent<{}>) => void;
  props: React.Props<ReactChild>;
  children: ReactElement | ReactElement[];
};
export type ReactChild = ReactElement<ChildProps> | ReactElement;

И машинопись продолжает говорить, что есть проблема с моим props на child.props.children.

enter image description here

Сообщение:

Свойство 'props' не существует для типа 'ReactNode'. Свойство 'props' не существует для типа 'string'.

Что я делаю не так?

1 Ответ

1 голос
/ 28 марта 2020

Вы можете переместить / добавить тип к аргументу обратного вызова map, поскольку теперь он применяется только к первому аргументу React.cloneElement.

const childrenWithProps = React.Children.map(children, (child: ReactChild) => // <- Here
  React.cloneElement(child, { // <- Assertion here can be omitted
    onClick: (e: React.FormEvent) =>
      childrenClickHandler(
        e,
        child.props.children,
        onItemClick && onItemClick(e),
      ),
  }),
);

Утверждение имеет ту же область действия, что и переменная, поэтому

React.Children.map(children, child => ...)

без типа делает child тип any (если вы не указали тип children каким-либо образом)

Тогда child используется в качестве аргумента и зависит для типа функции и вашего tsconfig может потребоваться значение какого-то типа

React.cloneElement(child, ...)

. Вы ставите здесь утверждение, но это влияет на использование child в качестве аргумента. На самом деле можно применить то же утверждение ко второму использованию:

  React.cloneElement(child as ReactChild, {
    onClick: (e: React.FormEvent) =>
      childrenClickHandler(
        e,
        (child as ReactChild).props.children, // <- Here
        onItemClick && onItemClick(e),
      ),
  }),

Но в этом случае лучше указать тип переменной, в которой она определена, чтобы она имела одинаковый тип во всех его сфера применения.

...