Skip to content

Commit

Permalink
chore(Table): use React.forwardRef() (#4239)
Browse files Browse the repository at this point in the history
* chore(Table): use React.forwardRef()

* fix naming
  • Loading branch information
layershifter committed Dec 13, 2022
1 parent 50d8109 commit c6625c3
Show file tree
Hide file tree
Showing 16 changed files with 48 additions and 28 deletions.
9 changes: 5 additions & 4 deletions src/collections/Table/Table.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import TableRow from './TableRow'
/**
* A table displays a collections of data grouped into rows.
*/
function Table(props) {
const Table = React.forwardRef(function TableInner(props, ref) {
const {
attached,
basic,
Expand Down Expand Up @@ -88,7 +88,7 @@ function Table(props) {

if (!childrenUtils.isNil(children)) {
return (
<ElementType {...rest} className={classes}>
<ElementType {...rest} className={classes} ref={ref}>
{children}
</ElementType>
)
Expand All @@ -104,7 +104,7 @@ function Table(props) {
)

return (
<ElementType {...rest} className={classes}>
<ElementType {...rest} className={classes} ref={ref}>
{headerElement}
<TableBody>
{renderBodyRow &&
Expand All @@ -113,8 +113,9 @@ function Table(props) {
{footerRow && <TableFooter>{TableRow.create(footerRow)}</TableFooter>}
</ElementType>
)
}
})

Table.displayName = 'Table'
Table.defaultProps = {
as: 'table',
}
Expand Down
7 changes: 4 additions & 3 deletions src/collections/Table/TableBody.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,20 @@ import React from 'react'

import { getElementType, getUnhandledProps } from '../../lib'

function TableBody(props) {
const TableBody = React.forwardRef(function TableBodyInner(props, ref) {
const { children, className } = props
const classes = cx(className)
const rest = getUnhandledProps(TableBody, props)
const ElementType = getElementType(TableBody, props)

return (
<ElementType {...rest} className={classes}>
<ElementType {...rest} className={classes} ref={ref}>
{children}
</ElementType>
)
}
})

TableBody.displayName = 'TableBody'
TableBody.defaultProps = {
as: 'tbody',
}
Expand Down
9 changes: 5 additions & 4 deletions src/collections/Table/TableCell.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import Icon from '../../elements/Icon'
/**
* A table row can have cells.
*/
function TableCell(props) {
const TableCell = React.forwardRef(function TableCellInner(props, ref) {
const {
active,
children,
Expand Down Expand Up @@ -60,24 +60,25 @@ function TableCell(props) {

if (!childrenUtils.isNil(children)) {
return (
<ElementType {...rest} className={classes}>
<ElementType {...rest} className={classes} ref={ref}>
{children}
</ElementType>
)
}

return (
<ElementType {...rest} className={classes}>
<ElementType {...rest} className={classes} ref={ref}>
{Icon.create(icon)}
{content}
</ElementType>
)
}
})

TableCell.defaultProps = {
as: 'td',
}

TableCell.displayName = 'TableCell'
TableCell.propTypes = {
/** An element type to render as (string or function). */
as: PropTypes.elementType,
Expand Down
7 changes: 4 additions & 3 deletions src/collections/Table/TableFooter.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ import TableHeader from './TableHeader'
/**
* A table can have a footer.
*/
function TableFooter(props) {
const TableFooter = React.forwardRef(function TableFooterInner(props, ref) {
const { as } = props
const rest = getUnhandledProps(TableFooter, props)

return <TableHeader {...rest} as={as} />
}
return <TableHeader {...rest} as={as} ref={ref} />
})

TableFooter.displayName = 'TableFooter'
TableFooter.propTypes = {
/** An element type to render as (string or function). */
as: PropTypes.elementType,
Expand Down
7 changes: 4 additions & 3 deletions src/collections/Table/TableHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,24 @@ import {
/**
* A table can have a header.
*/
function TableHeader(props) {
const TableHeader = React.forwardRef(function TableHeaderInner(props, ref) {
const { children, className, content, fullWidth } = props
const classes = cx(useKeyOnly(fullWidth, 'full-width'), className)
const rest = getUnhandledProps(TableHeader, props)
const ElementType = getElementType(TableHeader, props)

return (
<ElementType {...rest} className={classes}>
<ElementType {...rest} className={classes} ref={ref}>
{childrenUtils.isNil(children) ? content : children}
</ElementType>
)
}
})

TableHeader.defaultProps = {
as: 'thead',
}

TableHeader.displayName = 'TableHeader'
TableHeader.propTypes = {
/** An element type to render as (string or function). */
as: PropTypes.elementType,
Expand Down
7 changes: 4 additions & 3 deletions src/collections/Table/TableHeaderCell.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ import TableCell from './TableCell'
/**
* A table can have a header cell.
*/
function TableHeaderCell(props) {
const TableHeaderCell = React.forwardRef(function TableHeaderCellInner(props, ref) {
const { as, className, sorted } = props
const classes = cx(useValueAndKey(sorted, 'sorted'), className)
const rest = getUnhandledProps(TableHeaderCell, props)

return <TableCell {...rest} as={as} className={classes} />
}
return <TableCell {...rest} as={as} className={classes} ref={ref} />
})

TableHeaderCell.displayName = 'TableHeaderCell'
TableHeaderCell.propTypes = {
/** An element type to render as (string or function). */
as: PropTypes.elementType,
Expand Down
9 changes: 5 additions & 4 deletions src/collections/Table/TableRow.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import TableCell from './TableCell'
/**
* A table can have rows.
*/
function TableRow(props) {
const TableRow = React.forwardRef(function TableRowInner(props, ref) {
const {
active,
cellAs,
Expand Down Expand Up @@ -51,24 +51,25 @@ function TableRow(props) {

if (!childrenUtils.isNil(children)) {
return (
<ElementType {...rest} className={classes}>
<ElementType {...rest} className={classes} ref={ref}>
{children}
</ElementType>
)
}

return (
<ElementType {...rest} className={classes}>
<ElementType {...rest} className={classes} ref={ref}>
{_.map(cells, (cell) => TableCell.create(cell, { defaultProps: { as: cellAs } }))}
</ElementType>
)
}
})

TableRow.defaultProps = {
as: 'tr',
cellAs: 'td',
}

TableRow.displayName = 'TableRow'
TableRow.propTypes = {
/** An element type to render as (string or function). */
as: PropTypes.elementType,
Expand Down
2 changes: 2 additions & 0 deletions test/specs/collections/Table/Table-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import * as _ from 'lodash'

describe('Table', () => {
common.isConformant(Table)
common.forwardsRef(Table, { tagName: 'table' })
common.forwardsRef(Table, { requiredProps: { children: <tbody /> }, tagName: 'table' })
common.hasSubcomponents(Table, [
TableBody,
TableCell,
Expand Down
1 change: 1 addition & 0 deletions test/specs/collections/Table/TableBody-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import TableBody from 'src/collections/Table/TableBody'

describe('TableBody', () => {
common.isConformant(TableBody)
common.forwardsRef(TableBody, { tagName: 'tbody' })
common.rendersChildren(TableBody, {
rendersContent: false,
})
Expand Down
2 changes: 2 additions & 0 deletions test/specs/collections/Table/TableCell-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { SUI } from 'src/lib'

describe('TableCell', () => {
common.isConformant(TableCell)
common.forwardsRef(TableCell, { tagName: 'td' })
common.forwardsRef(TableCell, { requiredProps: { children: <span /> }, tagName: 'td' })
common.rendersChildren(TableCell)

common.implementsCreateMethod(TableCell)
Expand Down
1 change: 1 addition & 0 deletions test/specs/collections/Table/TableFooter-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import TableFooter from 'src/collections/Table/TableFooter'

describe('TableFooter', () => {
common.isConformant(TableFooter)
common.forwardsRef(TableFooter, { tagName: 'tfoot' })

it('renders as a tfoot by default', () => {
shallow(<TableFooter />).should.have.tagName('tfoot')
Expand Down
1 change: 1 addition & 0 deletions test/specs/collections/Table/TableHeader-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import TableHeader from 'src/collections/Table/TableHeader'

describe('TableHeader', () => {
common.isConformant(TableHeader)
common.forwardsRef(TableHeader, { tagName: 'thead' })
common.rendersChildren(TableHeader)

common.propKeyOnlyToClassName(TableHeader, 'fullWidth', {
Expand Down
1 change: 1 addition & 0 deletions test/specs/collections/Table/TableHeaderCell-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import TableHeaderCell from 'src/collections/Table/TableHeaderCell'

describe('TableHeaderCell', () => {
common.isConformant(TableHeaderCell)
common.forwardsRef(TableHeaderCell, { tagName: 'th' })
common.propKeyAndValueToClassName(TableHeaderCell, 'sorted', ['ascending', 'descending'])

it('renders as a th by default', () => {
Expand Down
2 changes: 2 additions & 0 deletions test/specs/collections/Table/TableRow-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import TableRow from 'src/collections/Table/TableRow'

describe('TableRow', () => {
common.isConformant(TableRow)
common.forwardsRef(TableRow, { tagName: 'tr' })
common.forwardsRef(TableRow, { requiredProps: { children: <span /> }, tagName: 'tr' })
common.rendersChildren(TableRow, {
rendersContent: false,
})
Expand Down
7 changes: 5 additions & 2 deletions test/specs/commonTests/forwardsRef.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import React from 'react'
import { sandbox } from 'test/utils'
import { consoleUtil, sandbox } from 'test/utils'

/**
* Assert a Component correctly implements a shorthand create method.
* @param {React.Component} Component The component to test
* @param {{ requiredProps?: Object, tagName?: string }} options Options for a test
*/
export default function implementsCreateMethod(Component, options = {}) {
export default function forwardsRef(Component, options = {}) {
describe('forwardsRef', () => {
const { requiredProps = {}, tagName = 'div' } = options

it(`forwards ref to "${tagName}"`, () => {
const ref = sandbox.spy()

// mount() can produce "validateNesting" error from React when elements like "td" are mounted
consoleUtil.disableOnce()
mount(<Component {...requiredProps} ref={ref} />)

ref.should.have.been.calledOnce()
Expand Down
4 changes: 2 additions & 2 deletions test/specs/elements/Header/Header-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import * as common from 'test/specs/commonTests'

describe('Header', () => {
common.hasUIClassName(Header)
common.forwardsRef(Header, { children: <span /> })
common.forwardsRef(Header, { icon: 'book' })
common.forwardsRef(Header, { requiredProps: { children: <span /> } })
common.forwardsRef(Header, { requiredProps: { icon: 'book' } })
common.hasSubcomponents(Header, [HeaderContent, HeaderSubheader])
common.rendersChildren(Header)

Expand Down

0 comments on commit c6625c3

Please sign in to comment.