From 8d956272bc9d7a9186bd4d1890bd40e15e764582 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Wed, 6 Feb 2019 10:17:30 +0100 Subject: [PATCH 1/3] [utils] Add support for forwardRef components in getDisplayName --- .eslintrc.js | 3 +- .../material-ui-utils/src/getDisplayName.js | 45 +++++++++++++++++-- .../src/getDisplayName.test.js | 16 +++++++ packages/material-ui/src/Backdrop/Backdrop.js | 4 +- packages/material-ui/src/List/List.js | 4 +- packages/material-ui/src/ListItem/ListItem.js | 4 +- packages/material-ui/src/MenuItem/MenuItem.js | 4 +- .../material-ui/src/MenuList/MenuList.test.js | 1 - packages/material-ui/src/Paper/Paper.js | 4 +- 9 files changed, 64 insertions(+), 21 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 4e9d60926951f0..224fdc5c79d026 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -51,6 +51,7 @@ module.exports = { 'react/no-find-dom-node': 'off', 'jsx-a11y/no-autofocus': 'off', // We are a library, people do what they want. + 'prefer-arrow-callback': ['error', { allowNamedFunctions: true }], 'prefer-destructuring': 'off', // Destructuring harm grep potential. 'consistent-this': ['error', 'self'], 'max-len': [ @@ -90,7 +91,7 @@ module.exports = { 'mocha/no-sibling-hooks': 'error', 'mocha/no-skipped-tests': 'error', 'mocha/no-top-level-hooks': 'error', - 'mocha/prefer-arrow-callback': 'error', + 'mocha/prefer-arrow-callback': ['error', { allowNamedFunctions: true }], 'mocha/valid-suite-description': 'error', }, }; diff --git a/packages/material-ui-utils/src/getDisplayName.js b/packages/material-ui-utils/src/getDisplayName.js index 08cbb522beccde..65f2c4b8e8d11b 100644 --- a/packages/material-ui-utils/src/getDisplayName.js +++ b/packages/material-ui-utils/src/getDisplayName.js @@ -1,4 +1,4 @@ -// Fork of recompose/getDisplayName with added IE 11 support +import { ForwardRef } from 'react-is'; // Simplified polyfill for IE 11 support // https://github.com/JamesMGreene/Function.name/blob/58b314d4a983110c3682f1228f845d39ccca1817/Function.name.js#L3 @@ -9,16 +9,53 @@ export function getFunctionName(fn) { return name || ''; } +/** + * @param {function} Component + * @param {string} fallback + * @returns {string | undefined} + */ +function getFunctionComponentName(Component, fallback = '') { + return Component.displayName || Component.name || getFunctionName(Component) || fallback; +} + +function getWrappedName(outerType, innerType, wrapperName) { + const functionName = getFunctionComponentName(innerType); + return ( + outerType.displayName || (functionName !== '' ? `${wrapperName}(${functionName})` : wrapperName) + ); +} + +/** + * cherry-pick from + * https://github.com/facebook/react/blob/769b1f270e1251d9dbdce0fcbd9e92e502d059b8/packages/shared/getComponentName.js + * originally forked from recompose/getDisplayName with added IE 11 support + * + * @param {React.ReactType} Component + * @returns {string | undefined} + */ function getDisplayName(Component) { + if (Component == null) { + return undefined; + } + if (typeof Component === 'string') { return Component; } - if (!Component) { - return undefined; + if (typeof Component === 'function') { + return getFunctionComponentName(Component, 'Component'); + } + + if (typeof Component === 'object') { + switch (Component.$$typeof) { + case ForwardRef: + return getWrappedName(Component, Component.render, 'ForwardRef'); + default: + return undefined; + } } - return Component.displayName || Component.name || getFunctionName(Component) || 'Component'; + return undefined; } export default getDisplayName; diff --git a/packages/material-ui-utils/src/getDisplayName.test.js b/packages/material-ui-utils/src/getDisplayName.test.js index abbc20f7bed82a..91352be244e00c 100644 --- a/packages/material-ui-utils/src/getDisplayName.test.js +++ b/packages/material-ui-utils/src/getDisplayName.test.js @@ -27,6 +27,19 @@ describe('utils/getDisplayName.js', () => { const AndAnotherComponent = () =>
; + const AnonymousForwardRefComponent = React.forwardRef((props, ref) => ( +
+ )); + + const ForwardRefComponent = React.forwardRef(function Div(props, ref) { + return
; + }); + + const NamedForwardRefComponent = React.forwardRef((props, ref) => ( +
+ )); + NamedForwardRefComponent.displayName = 'Div'; + assert.strictEqual(getDisplayName(SomeComponent), 'SomeComponent'); assert.strictEqual(getDisplayName(SomeOtherComponent), 'CustomDisplayName'); assert.strictEqual(getDisplayName(YetAnotherComponent), 'YetAnotherComponent'); @@ -34,6 +47,9 @@ describe('utils/getDisplayName.js', () => { assert.strictEqual(getDisplayName(() =>
), 'Component'); assert.strictEqual(getDisplayName('div'), 'div'); assert.strictEqual(getDisplayName(), undefined); + assert.strictEqual(getDisplayName(AnonymousForwardRefComponent), 'ForwardRef'); + assert.strictEqual(getDisplayName(ForwardRefComponent), 'ForwardRef(Div)'); + assert.strictEqual(getDisplayName(NamedForwardRefComponent), 'Div'); }); }); diff --git a/packages/material-ui/src/Backdrop/Backdrop.js b/packages/material-ui/src/Backdrop/Backdrop.js index 21ca6292e18456..a68849214bf099 100644 --- a/packages/material-ui/src/Backdrop/Backdrop.js +++ b/packages/material-ui/src/Backdrop/Backdrop.js @@ -25,7 +25,7 @@ export const styles = { }, }; -const Backdrop = React.forwardRef((props, ref) => { +const Backdrop = React.forwardRef(function Backdrop(props, ref) { const { classes, className, invisible, open, transitionDuration, ...other } = props; return ( @@ -46,8 +46,6 @@ const Backdrop = React.forwardRef((props, ref) => { ); }); -Backdrop.displayName = 'Backdrop'; - Backdrop.propTypes = { /** * Override or extend the styles applied to the component. diff --git a/packages/material-ui/src/List/List.js b/packages/material-ui/src/List/List.js index f9ffc500a237f5..0f1448cbaf80ff 100644 --- a/packages/material-ui/src/List/List.js +++ b/packages/material-ui/src/List/List.js @@ -29,7 +29,7 @@ export const styles = { }, }; -const List = React.forwardRef((props, ref) => { +const List = React.forwardRef(function List(props, ref) { const { children, classes, @@ -63,8 +63,6 @@ const List = React.forwardRef((props, ref) => { ); }); -List.displayName = 'List'; - List.propTypes = { /** * The content of the component. diff --git a/packages/material-ui/src/ListItem/ListItem.js b/packages/material-ui/src/ListItem/ListItem.js index 1247be5befabd7..bf2fae84c27769 100644 --- a/packages/material-ui/src/ListItem/ListItem.js +++ b/packages/material-ui/src/ListItem/ListItem.js @@ -86,7 +86,7 @@ export const styles = theme => ({ /** * Uses an additional container component if `ListItemSecondaryAction` is the last child. */ -const ListItem = React.forwardRef((props, ref) => { +const ListItem = React.forwardRef(function ListItem(props, ref) { const { alignItems, button, @@ -177,8 +177,6 @@ const ListItem = React.forwardRef((props, ref) => { ); }); -ListItem.displayName = 'ListItem'; - ListItem.propTypes = { /** * Defines the `align-items` style property. diff --git a/packages/material-ui/src/MenuItem/MenuItem.js b/packages/material-ui/src/MenuItem/MenuItem.js index 3baf841d5560db..74e52fb2435421 100644 --- a/packages/material-ui/src/MenuItem/MenuItem.js +++ b/packages/material-ui/src/MenuItem/MenuItem.js @@ -27,7 +27,7 @@ export const styles = theme => ({ selected: {}, }); -const MenuItem = React.forwardRef((props, ref) => { +const MenuItem = React.forwardRef(function MenuItem(props, ref) { const { classes, className, component, disableGutters, role, selected, ...other } = props; return ( @@ -52,8 +52,6 @@ const MenuItem = React.forwardRef((props, ref) => { ); }); -MenuItem.displayName = 'MenuItem'; - MenuItem.propTypes = { /** * Menu item contents. diff --git a/packages/material-ui/src/MenuList/MenuList.test.js b/packages/material-ui/src/MenuList/MenuList.test.js index 253ce4eb7052b2..ddd0af18767c01 100644 --- a/packages/material-ui/src/MenuList/MenuList.test.js +++ b/packages/material-ui/src/MenuList/MenuList.test.js @@ -28,7 +28,6 @@ describe('', () => { }); it('should render a List', () => { - assert.strictEqual(wrapper.name(), 'List'); assert.strictEqual(wrapper.props()['data-test'], 'hi'); assert.strictEqual(wrapper.hasClass('test-class'), true); }); diff --git a/packages/material-ui/src/Paper/Paper.js b/packages/material-ui/src/Paper/Paper.js index 741d5decd1e8e8..f0860b51e20c7c 100644 --- a/packages/material-ui/src/Paper/Paper.js +++ b/packages/material-ui/src/Paper/Paper.js @@ -26,7 +26,7 @@ export const styles = theme => { }; }; -const Paper = React.forwardRef((props, ref) => { +const Paper = React.forwardRef(function Paper(props, ref) { const { classes, className: classNameProp, @@ -53,8 +53,6 @@ const Paper = React.forwardRef((props, ref) => { return ; }); -Paper.displayName = 'Paper'; - Paper.propTypes = { /** * The content of the component. From 6f12753a71ffc3154c0d1c335956775f9a54a3f3 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Wed, 6 Feb 2019 10:28:35 +0100 Subject: [PATCH 2/3] [core] Fix umd build --- packages/material-ui/scripts/rollup.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/material-ui/scripts/rollup.config.js b/packages/material-ui/scripts/rollup.config.js index 4207842d7bd88b..aa5add25dcf8e6 100644 --- a/packages/material-ui/scripts/rollup.config.js +++ b/packages/material-ui/scripts/rollup.config.js @@ -21,7 +21,7 @@ const commonjsOptions = { ignoreGlobal: true, include: /node_modules/, namedExports: { - '../../node_modules/react-is/index.js': ['isValidElementType'], + '../../node_modules/react-is/index.js': ['ForwardRef', 'isValidElementType'], }, }; From 6a03bd617a3f6c7f58295e43c7aeb8ce214a23bf Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Wed, 6 Feb 2019 10:41:32 +0100 Subject: [PATCH 3/3] [core] update bundle size --- .size-limit.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.size-limit.js b/.size-limit.js index 4d158a3b908cdc..0d9994b6d57bf8 100644 --- a/.size-limit.js +++ b/.size-limit.js @@ -28,13 +28,13 @@ module.exports = [ name: 'The size of the @material-ui/core modules', webpack: true, path: 'packages/material-ui/build/index.js', - limit: '91.3 KB', + limit: '91.2 KB', }, { name: 'The size of the @material-ui/styles modules', webpack: true, path: 'packages/material-ui-styles/build/index.js', - limit: '16.3 KB', + limit: '16.4 KB', }, { name: 'The size of the @material-ui/system modules',