diff --git a/UNRELEASED.md b/UNRELEASED.md index a1655c0c08b..00f18f5f42e 100644 --- a/UNRELEASED.md +++ b/UNRELEASED.md @@ -25,6 +25,7 @@ ### Code quality - Converted `FormLayout` into a functional component ([#2539](https://github.com/Shopify/polaris-react/pull/2539)) +- Converted `Stack` into a functional component ([#2534](https://github.com/Shopify/polaris-react/pull/2534)) - Converted `BulkActionButton` into a functional component ([#2542](https://github.com/Shopify/polaris-react/pull/2542)) - Converted `Focus` into a functional component ([#2540](https://github.com/Shopify/polaris-react/pull/2540)) - Converted `Tooltip` into a functional component ([#2543](https://github.com/Shopify/polaris-react/pull/2543)) diff --git a/src/components/Stack/Stack.tsx b/src/components/Stack/Stack.tsx index 8287bcc4878..66d9b246e57 100644 --- a/src/components/Stack/Stack.tsx +++ b/src/components/Stack/Stack.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {memo, NamedExoticComponent} from 'react'; import {classNames, variationName} from '../../utilities/css'; import {elementChildren, wrapWithComponent} from '../../utilities/components'; @@ -32,33 +32,31 @@ export interface StackProps { distribution?: Distribution; } -export class Stack extends React.PureComponent { - static Item = Item; - - render() { - const { - children, - vertical, - spacing, - distribution, - alignment, - wrap, - } = this.props; - - const className = classNames( - styles.Stack, - vertical && styles.vertical, - spacing && styles[variationName('spacing', spacing)], - distribution && styles[variationName('distribution', distribution)], - alignment && styles[variationName('alignment', alignment)], - wrap === false && styles.noWrap, - ); - - const itemMarkup = elementChildren(children).map((child, index) => { - const props = {key: index}; - return wrapWithComponent(child, Item, props); - }); - - return
{itemMarkup}
; - } -} +export const Stack = memo(function Stack({ + children, + vertical, + spacing, + distribution, + alignment, + wrap, +}: StackProps) { + const className = classNames( + styles.Stack, + vertical && styles.vertical, + spacing && styles[variationName('spacing', spacing)], + distribution && styles[variationName('distribution', distribution)], + alignment && styles[variationName('alignment', alignment)], + wrap === false && styles.noWrap, + ); + + const itemMarkup = elementChildren(children).map((child, index) => { + const props = {key: index}; + return wrapWithComponent(child, Item, props); + }); + + return
{itemMarkup}
; +}) as NamedExoticComponent & { + Item: typeof Item; +}; + +Stack.Item = Item; diff --git a/tests/build.test.js b/tests/build.test.js index 22a88f69be3..7f71222ae5b 100644 --- a/tests/build.test.js +++ b/tests/build.test.js @@ -103,10 +103,10 @@ describe('build', () => { }); it('preserves classes to facilitate class-level tree shaking', () => { - // `Stack` is a foundation class, so is unlikely to disappear from the build. + // `Collapsible` deeply ties into the react class based life-cycles methods, so is likely to be one of the last components converted to a function. expect( - fs.readFileSync('esnext/components/Stack/Stack.js', 'utf8'), - ).toMatch('class Stack'); + fs.readFileSync('esnext/components/Collapsible/Collapsible.js', 'utf8'), + ).toMatch('class Collapsible'); }); it('preserves jsx to give consumers control over Babel transforms', () => {