如何写好一个React table component

最近上手做一个公司项目,前端用React, 所以为了减少冗余代码,对组件的复用率要求很高,这不需要一个React table component

为了实现当前的业务需求小编很快写了第一个component

       分析:table分为两个部分header和body,header是固定的,而body的列数固定,但是行数不固定。对于data,也就是table的body,是一个对象数组,每一个对象就是table的一行,对象的属性名称也是固定的。根据上述分析结果,我写了下面这个component。

1.第一个table component

 先上代码:

import React from 'react'
import PropTypes from 'prop-types'
import { Table } from 'react-bootstrap'
import { RowHead } from './style'

const TableHeader = props => {
    const { data, headerFormatter } = props
    return (
        <thead>
            <RowHead>
                {data &&
                    data.map(item => <th key={item}> {headerFormatter ? headerFormatter(item) : item}</th>)}
            </RowHead>

        </thead>
    )
}
TableHeader.propTypes = {
    data: PropTypes.arrayOf(PropTypes.string).isRequired,
    headerFormatter: PropTypes.func.isRequired,
}

const TableColumns = props => {
    const { data, columnNames, formatter } = props
    return (
        <tdoby>
            {data && columnNames &&
                data.map(item => (
                    <tr key={item.id}>
                        {columnNames.map(key => (
                            <td key={item.id}>{formatter(key, item[key], item.id)}</td>
                        ))}
                    </tr>
                ))}
        </tdoby>
    )
}
TableColumns.propTypes = {
    data: PropTypes.arrayOf(PropTypes.object).isRequired,
    columnNames: PropTypes.arrayOf(PropTypes.string).isRequired,
    formatter: PropTypes.func.isRequired,
}

const TableContainer = ({ data, headers, columnNames, formatter, headerFormatter }) => (
    <Table responsive>
        <TableHead data={header} headerFormatter={headerFormatter} />
        <TableColumns data={data} columnNames={columnNames} formatter={formatter} />
    </Table>
)
TableContainer.propTypes = {
    headers: PropTypes.arrayOf(PropTypes.string).isRequired,
    headerFormatter: PropTypes.func.isRequired,
    columnNames: PropTypes.arrayOf(PropTypes.string).isRequired,
    formatter: PropTypes.func.isRequired,
    data: PropTypes.arrayOf(PropTypes.object).isRequired,
}

export default TableContainer

      总结: 

       细心的同学不难发现,首先有许多重复的代码, TableContainer.propTypes TableHeader.propTypes  TableColumns.propTypes

       对于header,如果这么写,header就显示同样的format,不能实现对表头每一个名称进行个性化的定制。

       body同样的道理,使所有的行得每个元素都具有相同的format,或者在使用此component时,需要进行大量的判断,根据不同的字段,赋予不同的format。这种component简直有同于无。 

       很明显,不改进,codeReview肯定过不了。

2.第二个react table component 

import React from 'react'
import PropTypes from 'prop-types'
import { Table } from 'react-bootstrap'
import { RowHead } from './style'


const HeaderCell = props => {
    const { header, headerFormatter } = props
    return <th> {headerFormatter ? headerFormatter(header) : header} </th>
}
const HeaderCellPropTypes = {
    header: PropTypes.arrayOf(PropTypes.string).isRequired,
    headerFormatter: PropTypes.oneOfType([PropTypes.func, PropTypes.element]).isRequired,
}
HeaderCell.propTypes = HeaderCellPropTypes

const ColumnCell = props => {
    const { value, formatter, coluumnId } = props
    return <td> {formatter ? formatter(value, coluumnId) : value}</td>
}
ColumnCell.propTypes = {
    value: PropTypes.string.isRequired,
    formatter: PropTypes.oneOfType([PropTypes.func, PropTypes.element]).isRequired,
    coluumnId: PropTypes.string.isRequired,
}

const TableContainer = ({ cloumns, data }) => (
    <Table responsive>
        <thead>
            <RowHead>
                {cloumns &&
                    cloumns.map(item => (
                        <HeaderCell
                            key={item.header}
                            header={item.header}
                            headerFormatter={item.headerFormatter}
                        />
                    ))}
            </RowHead>
        </thead>
        <tbody>
            {data && cloumns && data.map(item => (
                <tr key={item.id}>
                    {cloumns.map(cell => (
                        <ColumnCell
                            key={item.id}
                            coluumnId={item.id}
                            formatter={item.formatter}
                            value={item[cell.accessor]}
                        />
                    ))}
                </tr>
            ))}
        </tbody>
    </Table>
)

TableContainer.propTypes = {
    cloumns: PropTypes.arrayOf(
        PropTypes.shape({
            ...HeaderCellPropTypes,
            accessor: PropTypes.oneOf(PropTypes.func, PropTypes.string),
            formatter: PropTypes.oneOfType([PropTypes.func, PropTypes.element]).isRequired,
        })
    ).isRequired,
    data: PropTypes.arrayOf(PropTypes.object).isRequired,
}

分析: 第一个Component的所有的不足,在第二个component中变成了优势。good

export default ReactTableComponent

猜你喜欢

转载自www.cnblogs.com/bug-mark/p/10099951.html