From ecb113da1e23f960c3d17f75f3bfe423e6f0f970 Mon Sep 17 00:00:00 2001 From: Andrew Musgrave Date: Tue, 30 Apr 2019 11:38:05 -0400 Subject: [PATCH 1/2] Add new context to combobox --- .../components/ComboBox/ComboBox.tsx | 117 ++++++++---------- .../ComboBox/components/Context/Context.tsx | 6 + .../ComboBox/components/Context/index.ts | 1 + .../components/TextField/TextField.tsx | 45 +++---- .../components/ComboBox/components/index.ts | 1 + .../Autocomplete/components/types.ts | 13 +- 6 files changed, 78 insertions(+), 105 deletions(-) create mode 100644 src/components/Autocomplete/components/ComboBox/components/Context/Context.tsx create mode 100644 src/components/Autocomplete/components/ComboBox/components/Context/index.ts diff --git a/src/components/Autocomplete/components/ComboBox/ComboBox.tsx b/src/components/Autocomplete/components/ComboBox/ComboBox.tsx index f44a12bf596..eb26b99bbf3 100644 --- a/src/components/Autocomplete/components/ComboBox/ComboBox.tsx +++ b/src/components/Autocomplete/components/ComboBox/ComboBox.tsx @@ -9,9 +9,9 @@ import ActionList from '../../../ActionList'; import Popover from '../../../Popover'; import {PreferredPosition} from '../../../PositionedOverlay'; import {ActionListItemDescriptor, Key} from '../../../../types'; -import {contextTypes} from '../types'; +import {ComboBoxContext} from '../types'; import KeypressListener from '../../../KeypressListener'; -import {TextField} from './components'; +import {TextField, Provider} from './components'; import styles from './ComboBox.scss'; @@ -58,17 +58,9 @@ export interface Props { onEndReached?(): void; } -export interface Context { - comboBoxId: string; - selectedOptionId?: string; - subscribe(callback: () => void): void; - unsubscribe(callback: () => void): void; -} - export default class ComboBox extends React.PureComponent { static TextField = TextField; static OptionList = OptionList; - static childContextTypes = contextTypes; static getDerivedStateFromProps( { @@ -123,17 +115,14 @@ export default class ComboBox extends React.PureComponent { popoverWasActive: false, }; - private subscriptions: {(): void}[] = []; private popoverScrollContainer: React.RefObject< HTMLDivElement > = React.createRef(); - getChildContext(): Context { + get getContext(): ComboBoxContext { return { comboBoxId: this.state.comboBoxId, selectedOptionId: this.selectedOptionId, - subscribe: this.subscribe, - unsubscribe: this.unsubscribe, }; } @@ -161,7 +150,6 @@ export default class ComboBox extends React.PureComponent { componentDidUpdate(_: Props, prevState: State) { const {contentBefore, contentAfter, emptyState} = this.props; const {navigableOptions, popoverActive, popoverWasActive} = this.state; - this.subscriptions.forEach((subscriberCallback) => subscriberCallback()); const optionsChanged = navigableOptions && @@ -253,63 +241,58 @@ export default class ComboBox extends React.PureComponent { emptyState &&
{emptyState}
; return ( -
- - - - - +
-
+ + + + - {scrollListenerMarkup} - {contentBefore} - {actionsBeforeMarkup} - {optionsMarkup} - {actionsAfterMarkup} - {contentAfter} - {emptyStateMarkup} -
- -
+
+ {scrollListenerMarkup} + {contentBefore} + {actionsBeforeMarkup} + {optionsMarkup} + {actionsAfterMarkup} + {contentAfter} + {emptyStateMarkup} +
+
+
+ ); } - subscribe = (callback: () => void) => { - this.subscriptions.push(callback); - }; - - unsubscribe = (callback: () => void) => { - this.subscriptions = this.subscriptions.filter( - (subscription) => subscription !== callback, - ); - }; - private handleDownArrow = () => { const {selectedIndex, navigableOptions} = this.state; const {onEndReached} = this.props; diff --git a/src/components/Autocomplete/components/ComboBox/components/Context/Context.tsx b/src/components/Autocomplete/components/ComboBox/components/Context/Context.tsx new file mode 100644 index 00000000000..efe1ad83653 --- /dev/null +++ b/src/components/Autocomplete/components/ComboBox/components/Context/Context.tsx @@ -0,0 +1,6 @@ +import * as React from 'react'; +import {ComboBoxContext} from '../../../types'; + +const {Provider, Consumer} = React.createContext({}); + +export {Provider, Consumer}; diff --git a/src/components/Autocomplete/components/ComboBox/components/Context/index.ts b/src/components/Autocomplete/components/ComboBox/components/Context/index.ts new file mode 100644 index 00000000000..e45eea34bd9 --- /dev/null +++ b/src/components/Autocomplete/components/ComboBox/components/Context/index.ts @@ -0,0 +1 @@ +export {Provider, Consumer} from './Context'; diff --git a/src/components/Autocomplete/components/ComboBox/components/TextField/TextField.tsx b/src/components/Autocomplete/components/ComboBox/components/TextField/TextField.tsx index 9787d6b6254..7b8a8c2aa65 100644 --- a/src/components/Autocomplete/components/ComboBox/components/TextField/TextField.tsx +++ b/src/components/Autocomplete/components/ComboBox/components/TextField/TextField.tsx @@ -1,34 +1,21 @@ import * as React from 'react'; -import {contextTypes} from '../../../types'; +import {ComboBoxContext} from 'components/Autocomplete/components/types'; import BaseTextField, {Props as TextFieldProps} from '../../../../../TextField'; +import {Consumer} from '../Context'; -export default class TextField extends React.PureComponent< - TextFieldProps, - never -> { - static contextTypes = contextTypes; - - componentDidMount() { - const {subscribe} = this.context; - subscribe(this.handleContextUpdate); - } - - render() { - const {selectedOptionId, comboBoxId} = this.context; - - return ( - - ); - } - - private handleContextUpdate = () => { - this.forceUpdate(); - }; +export default function TextField(props: TextFieldProps) { + return ( + + {({selectedOptionId, comboBoxId}: ComboBoxContext) => ( + + )} + + ); } diff --git a/src/components/Autocomplete/components/ComboBox/components/index.ts b/src/components/Autocomplete/components/ComboBox/components/index.ts index 6237903f6d0..1840ed5f493 100644 --- a/src/components/Autocomplete/components/ComboBox/components/index.ts +++ b/src/components/Autocomplete/components/ComboBox/components/index.ts @@ -1 +1,2 @@ export {default as TextField} from './TextField'; +export {Provider, Consumer} from './Context'; diff --git a/src/components/Autocomplete/components/types.ts b/src/components/Autocomplete/components/types.ts index 31cff0e7604..db46d64551b 100644 --- a/src/components/Autocomplete/components/types.ts +++ b/src/components/Autocomplete/components/types.ts @@ -1,9 +1,4 @@ -import * as PropTypes from 'prop-types'; -import {ValidationMap} from 'react'; - -export const contextTypes: ValidationMap = { - selectedOptionId: PropTypes.string, - comboBoxId: PropTypes.string, - subscribe: PropTypes.func, - unsubscribe: PropTypes.func, -}; +export interface ComboBoxContext { + comboBoxId?: string; + selectedOptionId?: string; +} From 9146cca3ef88047da6c7704d60a7a074dced15cc Mon Sep 17 00:00:00 2001 From: Andrew Musgrave Date: Thu, 2 May 2019 18:11:19 -0400 Subject: [PATCH 2/2] changelog Fix path --- UNRELEASED-V4.md | 1 + .../components/ComboBox/components/TextField/TextField.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/UNRELEASED-V4.md b/UNRELEASED-V4.md index 5117c3b7c20..63056d20356 100644 --- a/UNRELEASED-V4.md +++ b/UNRELEASED-V4.md @@ -22,6 +22,7 @@ Use [the changelog guidelines](https://git.io/polaris-changelog-guidelines) to f ### Code quality +- Upgraded the `Autocomplete` component from legacy context API to use createContext ([#1403](https://github.com/Shopify/polaris-react/pull/1403)) - Updated `AppProvider` to no longer use `componentWillReceiveProps`([#1255](https://github.com/Shopify/polaris-react/pull/1255)) - Updated `ThemeProvider` to no longer use `componentWillReceiveProps`([#1254](https://github.com/Shopify/polaris-react/pull/1254)) - Upgraded the `Banner`, `Card`, and `Modal` components from legacy context API to use createContext ([#786](https://github.com/Shopify/polaris-react/pull/786)) diff --git a/src/components/Autocomplete/components/ComboBox/components/TextField/TextField.tsx b/src/components/Autocomplete/components/ComboBox/components/TextField/TextField.tsx index 7b8a8c2aa65..84927238a07 100644 --- a/src/components/Autocomplete/components/ComboBox/components/TextField/TextField.tsx +++ b/src/components/Autocomplete/components/ComboBox/components/TextField/TextField.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; -import {ComboBoxContext} from 'components/Autocomplete/components/types'; +import {ComboBoxContext} from '../../../types'; import BaseTextField, {Props as TextFieldProps} from '../../../../../TextField'; import {Consumer} from '../Context';