在Typescript中将prop递归映射到React子级

时间:2019-06-11 11:47:31

标签: reactjs typescript recursion typing

我正在创建一个React绑定层,以在UI库和SDK之间创建简单的连接。

为此,我将属性从父组件递归映射到节点中的每个子组件,例如:

<Bookies.UserBookieList>
  <BookieBarItem />
</Bookies.UserBookieList>

其中Bookies.UserBookieList将对其孩子和该孩子的孩子等应用一组道具/方法。

递归映射函数如下:

import React, { PropsWithChildren, ReactElement } from 'react';

export default function recursivelyMapChildren<AddedProperties>(
  children: ReactElement<PropsWithChildren<AddedProperties>>[],
  addedProperties: AddedProperties
): any {
  return React.Children.map(children, child => {
    if (!child.props.children) {
      return React.cloneElement<PropsWithChildren<AddedProperties>>(child, addedProperties);
    }
    if (React.isValidElement(child)) {
      return React.cloneElement<PropsWithChildren<AddedProperties>>(
        child,
        addedProperties,
        ...recursivelyMapChildren<PropsWithChildren<AddedProperties>>(
          child.props.children as ReactElement<PropsWithChildren<AddedProperties>>[],
          addedProperties
        )
      );
    }
    return child;
  });
}

这是Bookies.UserBookieList的使用方式:

interface UserBookieListChildProps {
  code: string;
  name: string;
  bookiePosition: number;
  index: number;
  isActive: boolean;
  loggedIn: boolean;
  onBookieSelect: (bookie: any, bookiePosition: number) => void;
}

class UserBookieList extends PureComponent<UserBookieListProps> {
  public handleBookieSelect = (bookie: any, bookiePosition: number) => {
    this.props.setClientBookie(bookie);

    trackEvent(TRACKING_EVENTS.USER_BOOKIE_SELECT, {
      betBookie: bookie,
      clickPosition: bookiePosition
    });
  };

  public render(): ReactElement<UserBookieListChildProps>[] {
    const { bookie: { code }, children, userBookies } = this.props;
    return userBookies.map((bookie: any, index: number) =>
      recursiveMap<UserBookieListChildProps>(children, {
        ...bookie,
        key: index,
        bookiePosition: index + 1,
        index,
        isActive: bookie.code === code,
        onBookieSelect: this.handleBookieSelect
      }).shift()
    );
  }
}

问题是我在编辑器和编译过程中收到以下错误,因为子组件不知道父组件正在提供所需的道具。

TS2740: Type '{}' is missing the following properties from type 'Readonly<BookieBarItemProps>': code, index, isActive, loggedIn, and 2 more.

我认为将UserBookieListChildProps接口提供给recursiveMap并将其传递给React.cloneElement作为元素道具输入会达到目的,但是并没有...

任何帮助将不胜感激!

0 个答案:

没有答案