From c6625c3236d1c781139fc705bc9685a15f01907d Mon Sep 17 00:00:00 2001 From: Oleksandr Fediashov Date: Mon, 26 Jul 2021 12:19:59 +0200 Subject: [PATCH] chore(Table): use React.forwardRef() (#4239) * chore(Table): use React.forwardRef() * fix naming --- src/collections/Table/Table.js | 9 +++++---- src/collections/Table/TableBody.js | 7 ++++--- src/collections/Table/TableCell.js | 9 +++++---- src/collections/Table/TableFooter.js | 7 ++++--- src/collections/Table/TableHeader.js | 7 ++++--- src/collections/Table/TableHeaderCell.js | 7 ++++--- src/collections/Table/TableRow.js | 9 +++++---- test/specs/collections/Table/Table-test.js | 2 ++ test/specs/collections/Table/TableBody-test.js | 1 + test/specs/collections/Table/TableCell-test.js | 2 ++ test/specs/collections/Table/TableFooter-test.js | 1 + test/specs/collections/Table/TableHeader-test.js | 1 + test/specs/collections/Table/TableHeaderCell-test.js | 1 + test/specs/collections/Table/TableRow-test.js | 2 ++ test/specs/commonTests/forwardsRef.js | 7 +++++-- test/specs/elements/Header/Header-test.js | 4 ++-- 16 files changed, 48 insertions(+), 28 deletions(-) diff --git a/src/collections/Table/Table.js b/src/collections/Table/Table.js index 3809dc48c5..e5cc5f1248 100644 --- a/src/collections/Table/Table.js +++ b/src/collections/Table/Table.js @@ -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, @@ -88,7 +88,7 @@ function Table(props) { if (!childrenUtils.isNil(children)) { return ( - + {children} ) @@ -104,7 +104,7 @@ function Table(props) { ) return ( - + {headerElement} {renderBodyRow && @@ -113,8 +113,9 @@ function Table(props) { {footerRow && {TableRow.create(footerRow)}} ) -} +}) +Table.displayName = 'Table' Table.defaultProps = { as: 'table', } diff --git a/src/collections/Table/TableBody.js b/src/collections/Table/TableBody.js index 258bd512e4..8d8585795f 100644 --- a/src/collections/Table/TableBody.js +++ b/src/collections/Table/TableBody.js @@ -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 ( - + {children} ) -} +}) +TableBody.displayName = 'TableBody' TableBody.defaultProps = { as: 'tbody', } diff --git a/src/collections/Table/TableCell.js b/src/collections/Table/TableCell.js index 848f36a4eb..2f985de73d 100644 --- a/src/collections/Table/TableCell.js +++ b/src/collections/Table/TableCell.js @@ -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, @@ -60,24 +60,25 @@ function TableCell(props) { if (!childrenUtils.isNil(children)) { return ( - + {children} ) } return ( - + {Icon.create(icon)} {content} ) -} +}) TableCell.defaultProps = { as: 'td', } +TableCell.displayName = 'TableCell' TableCell.propTypes = { /** An element type to render as (string or function). */ as: PropTypes.elementType, diff --git a/src/collections/Table/TableFooter.js b/src/collections/Table/TableFooter.js index 0f6d7e0989..b61078d049 100644 --- a/src/collections/Table/TableFooter.js +++ b/src/collections/Table/TableFooter.js @@ -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 -} + return +}) +TableFooter.displayName = 'TableFooter' TableFooter.propTypes = { /** An element type to render as (string or function). */ as: PropTypes.elementType, diff --git a/src/collections/Table/TableHeader.js b/src/collections/Table/TableHeader.js index 7994531b6e..b2840d5a31 100644 --- a/src/collections/Table/TableHeader.js +++ b/src/collections/Table/TableHeader.js @@ -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 ( - + {childrenUtils.isNil(children) ? content : children} ) -} +}) TableHeader.defaultProps = { as: 'thead', } +TableHeader.displayName = 'TableHeader' TableHeader.propTypes = { /** An element type to render as (string or function). */ as: PropTypes.elementType, diff --git a/src/collections/Table/TableHeaderCell.js b/src/collections/Table/TableHeaderCell.js index 7a2a1d2cb3..cb76db1812 100644 --- a/src/collections/Table/TableHeaderCell.js +++ b/src/collections/Table/TableHeaderCell.js @@ -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 -} + return +}) +TableHeaderCell.displayName = 'TableHeaderCell' TableHeaderCell.propTypes = { /** An element type to render as (string or function). */ as: PropTypes.elementType, diff --git a/src/collections/Table/TableRow.js b/src/collections/Table/TableRow.js index 9c9bb019d5..10ea1b4655 100644 --- a/src/collections/Table/TableRow.js +++ b/src/collections/Table/TableRow.js @@ -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, @@ -51,24 +51,25 @@ function TableRow(props) { if (!childrenUtils.isNil(children)) { return ( - + {children} ) } return ( - + {_.map(cells, (cell) => TableCell.create(cell, { defaultProps: { as: cellAs } }))} ) -} +}) TableRow.defaultProps = { as: 'tr', cellAs: 'td', } +TableRow.displayName = 'TableRow' TableRow.propTypes = { /** An element type to render as (string or function). */ as: PropTypes.elementType, diff --git a/test/specs/collections/Table/Table-test.js b/test/specs/collections/Table/Table-test.js index d65894082a..6629d521a4 100644 --- a/test/specs/collections/Table/Table-test.js +++ b/test/specs/collections/Table/Table-test.js @@ -13,6 +13,8 @@ import * as _ from 'lodash' describe('Table', () => { common.isConformant(Table) + common.forwardsRef(Table, { tagName: 'table' }) + common.forwardsRef(Table, { requiredProps: { children: }, tagName: 'table' }) common.hasSubcomponents(Table, [ TableBody, TableCell, diff --git a/test/specs/collections/Table/TableBody-test.js b/test/specs/collections/Table/TableBody-test.js index 6244bbd5c8..6e55c0e30f 100644 --- a/test/specs/collections/Table/TableBody-test.js +++ b/test/specs/collections/Table/TableBody-test.js @@ -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, }) diff --git a/test/specs/collections/Table/TableCell-test.js b/test/specs/collections/Table/TableCell-test.js index e35480635c..f3ab95329e 100644 --- a/test/specs/collections/Table/TableCell-test.js +++ b/test/specs/collections/Table/TableCell-test.js @@ -6,6 +6,8 @@ import { SUI } from 'src/lib' describe('TableCell', () => { common.isConformant(TableCell) + common.forwardsRef(TableCell, { tagName: 'td' }) + common.forwardsRef(TableCell, { requiredProps: { children: }, tagName: 'td' }) common.rendersChildren(TableCell) common.implementsCreateMethod(TableCell) diff --git a/test/specs/collections/Table/TableFooter-test.js b/test/specs/collections/Table/TableFooter-test.js index 5e43c10106..b231ea3438 100644 --- a/test/specs/collections/Table/TableFooter-test.js +++ b/test/specs/collections/Table/TableFooter-test.js @@ -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().should.have.tagName('tfoot') diff --git a/test/specs/collections/Table/TableHeader-test.js b/test/specs/collections/Table/TableHeader-test.js index 0f9de54fc8..020bee565e 100644 --- a/test/specs/collections/Table/TableHeader-test.js +++ b/test/specs/collections/Table/TableHeader-test.js @@ -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', { diff --git a/test/specs/collections/Table/TableHeaderCell-test.js b/test/specs/collections/Table/TableHeaderCell-test.js index ef5b54366a..b8012b6daf 100644 --- a/test/specs/collections/Table/TableHeaderCell-test.js +++ b/test/specs/collections/Table/TableHeaderCell-test.js @@ -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', () => { diff --git a/test/specs/collections/Table/TableRow-test.js b/test/specs/collections/Table/TableRow-test.js index c25efda41a..9ca6551fb0 100644 --- a/test/specs/collections/Table/TableRow-test.js +++ b/test/specs/collections/Table/TableRow-test.js @@ -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: }, tagName: 'tr' }) common.rendersChildren(TableRow, { rendersContent: false, }) diff --git a/test/specs/commonTests/forwardsRef.js b/test/specs/commonTests/forwardsRef.js index f7b7929292..ce6b11c396 100644 --- a/test/specs/commonTests/forwardsRef.js +++ b/test/specs/commonTests/forwardsRef.js @@ -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() ref.should.have.been.calledOnce() diff --git a/test/specs/elements/Header/Header-test.js b/test/specs/elements/Header/Header-test.js index 73e3acbbae..241afb386e 100644 --- a/test/specs/elements/Header/Header-test.js +++ b/test/specs/elements/Header/Header-test.js @@ -10,8 +10,8 @@ import * as common from 'test/specs/commonTests' describe('Header', () => { common.hasUIClassName(Header) - common.forwardsRef(Header, { children: }) - common.forwardsRef(Header, { icon: 'book' }) + common.forwardsRef(Header, { requiredProps: { children: } }) + common.forwardsRef(Header, { requiredProps: { icon: 'book' } }) common.hasSubcomponents(Header, [HeaderContent, HeaderSubheader]) common.rendersChildren(Header)