reactjs - typescript + React : define a generic table component

标签 reactjs typescript components typescript-generics

我花了两天时间努力制作一个可重复使用的表格,但我在类型方面遇到了问题。
我不是 typescript/react 专家,因为我更多地使用 javascript,所以我希望您向我展示开发此组件的正确方法。

信息:

typescript: "3.6.4"
react: "^16.11.0"

"engines": {
 "node": "10.x",
 "npm": "6.x"
}

我的想法是(不完整且有类型错误):

import * as React from 'react';

const getCellData = (fields: Record<string, string>, row) => {
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  return Object.entries(fields).reduce((res: Record<string, any>, val) => {
    res[val[0]] = row[val[1]];
    return res;
  }, {});
};

interface Props<C, R> {
  columns: C[];
  rows: R[];
}

const Table = <C, R>({ columns, rows }: Props<C, R>) => {
  return (
    <div className="table-responsive">
      <table className="table table-striped">
        <thead>
          <tr>
            {columns.map((column, i: number) => (
              <th scope="col" key={i}>
                {column.label}
              </th>
            ))}
          </tr>
        </thead>
        <tbody>
          {rows &&
            rows.map((row, j: number) => {
              return (
                <tr key={j}>
                  {columns.map((column, k: number) => {
                    const { Template, fields } = column;
                    const data = getCellData(fields, row);
                    return <td key={k}>{<Template {...data}></Template>}</td>;
                  })}
                </tr>
              );
            })}
        </tbody>
      </table>
    </div>
  );
};

export default Table;

我在 JSX 中使用这样的表(这样在 jsx 中传递类型是否正确?):

      <Table<SportsTableColumn, RedaxSport> columns={columns} rows={sports}></Table>

其中 SportsTableColumn 是:

export interface SportsTableColumn {
  label: string;
  Template: typeof TableTdText | typeof TableTdTextWithImage | typeof TableTdBoolCheck;
  fields: {
    text?: string;
    image?: string;
    checked?: string;
  };
}

TableTdText、TableTdTextWithImage、TableTdBoolCheck 是 React.FC

然后我们有 RedaxSport,它是一个具有如下属性的类:

this.sportId = sportId;
this.urlIcon = urlIcon;
this.redaxDescription = redaxDescription;
this.aamsDescription = aamsDescription;
this.isDailyProgram = isDailyProgram;

“列”数组数据示例:

[
  {
    label: intl.formatMessage({ id: 'sports.table.redaxDescription' }),
    Template: TableTdTextWithImage,
    fields: {
      text: 'redaxDescription',
      image: 'urlIcon'
    }
  },
  {
    label: intl.formatMessage({ id: 'sports.table.aamsDescription' }),
    Template: TableTdText,
    fields: {
      text: 'aamsDescription'
    }
  },
  {
    label: intl.formatMessage({ id: 'sports.table.dailyProgram' }),
    Template: TableTdBoolCheck,
    fields: {
      checked: 'isDailyProgram'
    }
  }
];

“行”数据示例:

[
  {
      "sportId": 0,
      "urlIcon": "https://url.com/",
      "redaxDescription": "This is a description",
      "aamsDescription": "Another description",
      "isDailyProgram": true
  },
  {
      "sportId": 1,
      "urlIcon": "https://url2.com/",
      "redaxDescription": "This is a description 2",
      "aamsDescription": "Another description 2",
      "isDailyProgram": false
  }
]

我只是希望能够明确我的意图并为您提供所需的所有信息。 谢谢

最佳答案

看看 generic table for example
可以重复使用,不需要很多代码
使用通用表的示例:

type MyElement = {
    firstName: string;
    lastName: string;
    age: number;
};

const elements: MyElement[] = [
    { firstName: 'A', lastName: 'A', age: 10 },
    { firstName: 'B', lastName: 'B', age: 11 },
    { firstName: 'C', lastName: 'C', age: 12 },
    { firstName: 'D', lastName: 'D', age: 13 },
    { firstName: 'E', lastName: 'E', age: 14 },
];

const model: TableModel<MyElement> = {
    columns: [
        {
            title: 'Name',
            html: e => <span>{e.firstName} {e.lastName}</span>
        },
        {
            title: 'Firstname',
            html: e => <span>{e.firstName}</span>
        },
        {
            title: 'Lastname',
            html: e => <span>{e.lastName}</span>
        },
        {
            title: 'Age',
            html: e => <span>{e.age}</span>
        },
    ]
};

export const Table = () => {
    return (
        <div className={styles.tableContainer}>
            <GenericTable model={model} elements={elements}></GenericTable>
        </div>
    );
};

关于reactjs - typescript + React : define a generic table component,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58875859/

相关文章:

angular - Angular 2 中的容器组件是什么

javascript - Emberjs 组件 Action

javascript - 解构值 nextjs : ReferenceError: Cannot access 'XXX' before initialization

javascript - 如何使用 TypeScript 和来自 github 的 Chartjs.definitelyTyped 来计算 Chartjs

typescript - 类型动态对象函数调用

javascript - 数组元素子类型

json - 什么是 axios.defaults.headers.post 'content-type' = 'application/json'

javascript - 在客户端 React 中存储 MSAL Graph API token 并重复使用它直至过期

javascript - Uncaught Error : Invariant Violation: Element type is invalid: expected a string

c# - 如何在 Windows 窗体应用程序中创建全局错误处理程序?