Skip to content

Commit 94fd404

Browse files
committed
refactor(CTable): improve syntax to limit the number of re-renders
1 parent 20960f1 commit 94fd404

File tree

3 files changed

+98
-64
lines changed

3 files changed

+98
-64
lines changed

packages/coreui-react/src/components/table/CTable.tsx

Lines changed: 55 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { CTableDataCell, CTableDataCellProps } from './CTableDataCell'
1010
import { CTableRow, CTableRowProps } from './CTableRow'
1111
import { CTableFoot, CTableFootProps } from './CTableFoot'
1212
import { CTableCaption } from './CTableCaption'
13+
import { CTableResponsiveWrapper } from './CTableResponsiveWrapper'
1314

1415
export interface CTableProps extends Omit<TableHTMLAttributes<HTMLTableElement>, 'align'> {
1516
/**
@@ -206,72 +207,62 @@ export const CTable = forwardRef<HTMLTableElement, CTableProps>(
206207
: pretifyName(column.key)
207208
: pretifyName(column)
208209

209-
const Table = () => (
210-
<table className={_className} {...rest} ref={ref}>
211-
{((caption && caption !== 'top') || captionTop) && (
212-
<CTableCaption>{caption || captionTop}</CTableCaption>
213-
)}
214-
{columns && (
215-
<CTableHead {...tableHeadProps}>
216-
<CTableRow>
217-
{columns.map((column: Column, index: number) => (
218-
<CTableHeaderCell
219-
{...(column._props && { ...column._props })}
220-
{...(column._style && { style: { ...column._style } })}
221-
key={index}
222-
>
223-
{label(column)}
224-
</CTableHeaderCell>
225-
))}
226-
</CTableRow>
227-
</CTableHead>
228-
)}
229-
{items && (
230-
<CTableBody>
231-
{items.map((item: Item, index: number) => (
232-
<CTableRow {...(item._props && { ...item._props })} key={index}>
233-
{rawColumnNames.map((colName: string, index: number) => {
234-
return item[colName] ? (
235-
<CTableDataCell
236-
{...(item._cellProps && {
237-
...(item._cellProps['all'] && { ...item._cellProps['all'] }),
238-
...(item._cellProps[colName] && { ...item._cellProps[colName] }),
239-
})}
240-
key={index}
241-
>
242-
{item[colName]}
243-
</CTableDataCell>
244-
) : null
245-
})}
210+
return (
211+
<CTableResponsiveWrapper responsive={responsive}>
212+
<table className={_className} {...rest} ref={ref}>
213+
{((caption && caption !== 'top') || captionTop) && (
214+
<CTableCaption>{caption || captionTop}</CTableCaption>
215+
)}
216+
{columns && (
217+
<CTableHead {...tableHeadProps}>
218+
<CTableRow>
219+
{columns.map((column: Column, index: number) => (
220+
<CTableHeaderCell
221+
{...(column._props && { ...column._props })}
222+
{...(column._style && { style: { ...column._style } })}
223+
key={index}
224+
>
225+
{label(column)}
226+
</CTableHeaderCell>
227+
))}
246228
</CTableRow>
247-
))}
248-
</CTableBody>
249-
)}
250-
{children}
251-
{footer && (
252-
<CTableFoot {...tableFootProps}>
253-
<CTableRow>
254-
{footer.map((item: FooterItem, index: number) => (
255-
<CTableDataCell {...(item._props && { ...item._props })} key={index}>
256-
{typeof item === 'object' ? item.label : item}
257-
</CTableDataCell>
229+
</CTableHead>
230+
)}
231+
{items && (
232+
<CTableBody>
233+
{items.map((item: Item, index: number) => (
234+
<CTableRow {...(item._props && { ...item._props })} key={index}>
235+
{rawColumnNames.map((colName: string, index: number) => {
236+
return item[colName] ? (
237+
<CTableDataCell
238+
{...(item._cellProps && {
239+
...(item._cellProps['all'] && { ...item._cellProps['all'] }),
240+
...(item._cellProps[colName] && { ...item._cellProps[colName] }),
241+
})}
242+
key={index}
243+
>
244+
{item[colName]}
245+
</CTableDataCell>
246+
) : null
247+
})}
248+
</CTableRow>
258249
))}
259-
</CTableRow>
260-
</CTableFoot>
261-
)}
262-
</table>
263-
)
264-
265-
return responsive ? (
266-
<div
267-
className={
268-
typeof responsive === 'boolean' ? 'table-responsive' : `table-responsive-${responsive}`
269-
}
270-
>
271-
<Table />
272-
</div>
273-
) : (
274-
<Table />
250+
</CTableBody>
251+
)}
252+
{children}
253+
{footer && (
254+
<CTableFoot {...tableFootProps}>
255+
<CTableRow>
256+
{footer.map((item: FooterItem, index: number) => (
257+
<CTableDataCell {...(item._props && { ...item._props })} key={index}>
258+
{typeof item === 'object' ? item.label : item}
259+
</CTableDataCell>
260+
))}
261+
</CTableRow>
262+
</CTableFoot>
263+
)}
264+
</table>
265+
</CTableResponsiveWrapper>
275266
)
276267
},
277268
)

packages/coreui-react/src/components/table/CTableDataCell.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ export interface CTableDataCellProps
2525
* @type 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'dark' | 'light' | string
2626
*/
2727
color?: Colors
28+
/**
29+
* @ignore
30+
*/
31+
colSpan?: number
2832
}
2933

3034
export const CTableDataCell = forwardRef<HTMLTableCellElement, CTableDataCellProps>(
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import React, { FC, HTMLAttributes } from 'react'
2+
import PropTypes from 'prop-types'
3+
4+
export interface CTableResponsiveWrapperProps extends HTMLAttributes<HTMLDivElement> {
5+
children: any
6+
/**
7+
* Make any table responsive across all viewports or pick a maximum breakpoint with which to have a responsive table up to.
8+
*/
9+
responsive?: boolean | 'sm' | 'md' | 'lg' | 'xl' | 'xxl'
10+
}
11+
12+
export const CTableResponsiveWrapper: FC<CTableResponsiveWrapperProps> = ({
13+
children,
14+
responsive,
15+
...rest
16+
}) => {
17+
return responsive ? (
18+
<div
19+
className={
20+
typeof responsive === 'boolean' ? 'table-responsive' : `table-responsive-${responsive}`
21+
}
22+
{...rest}
23+
>
24+
{children}
25+
</div>
26+
) : (
27+
children
28+
)
29+
}
30+
31+
CTableResponsiveWrapper.propTypes = {
32+
children: PropTypes.any,
33+
responsive: PropTypes.oneOfType([
34+
PropTypes.bool,
35+
PropTypes.oneOf<'sm' | 'md' | 'lg' | 'xl' | 'xxl'>(['sm', 'md', 'lg', 'xl', 'xxl']),
36+
]),
37+
}
38+
39+
CTableResponsiveWrapper.displayName = 'CTableResponsiveWrapper'

0 commit comments

Comments
 (0)