diff --git a/UNRELEASED.md b/UNRELEASED.md index 44cd8498a0f..8a1f01ee101 100644 --- a/UNRELEASED.md +++ b/UNRELEASED.md @@ -27,6 +27,7 @@ Use [the changelog guidelines](https://git.io/polaris-changelog-guidelines) to f ### Documentation +- Converted `ResourceList`, `ResourcePicker`, and `Select` examples to functional components ([#2133](https://github.com/Shopify/polaris-react/pull/2133)) - Converted `Collapsible`, `ColorPicker`, and `DataTable` examples to functional components ([#2128](https://github.com/Shopify/polaris-react/pull/2128)) - Updated the `withContext` section in the [v3 to v4 migration guide](https://github.com/Shopify/polaris-react/blob/master/documentation/guides/migrating-from-v3-to-v4.md) ([#2124](https://github.com/Shopify/polaris-react/pull/2124)) diff --git a/src/components/ResourceList/README.md b/src/components/ResourceList/README.md index 77f156347c5..e0c400cd33b 100644 --- a/src/components/ResourceList/README.md +++ b/src/components/ResourceList/README.md @@ -89,16 +89,43 @@ A resource list with simple items and no bulk actions, sorting, or filtering. A resource list with simple items and selection. ```jsx -class ResourceListExample extends React.Component { - state = { - selectedItems: [], - }; +function ResourceListWithSelectionExample() { + const [selectedItems, setSelectedItems] = useState([]); - handleSelectionChange = (selectedItems) => { - this.setState({selectedItems}); + const resourceName = { + singular: 'customer', + plural: 'customers', }; - renderItem = (item) => { + const items = [ + { + id: 341, + url: 'customers/341', + name: 'Mae Jemison', + location: 'Decatur, USA', + }, + { + id: 256, + url: 'customers/256', + name: 'Ellen Ochoa', + location: 'Los Angeles, USA', + }, + ]; + + return ( + + + + ); + + function renderItem(item) { const {id, url, name, location} = item; const media = ; @@ -115,41 +142,6 @@ class ResourceListExample extends React.Component {
{location}
); - }; - - render() { - const resourceName = { - singular: 'customer', - plural: 'customers', - }; - - const items = [ - { - id: 341, - url: 'customers/341', - name: 'Mae Jemison', - location: 'Decatur, USA', - }, - { - id: 256, - url: 'customers/256', - name: 'Ellen Ochoa', - location: 'Los Angeles, USA', - }, - ]; - - return ( - - - - ); } } ``` @@ -159,16 +151,66 @@ class ResourceListExample extends React.Component { Allows merchants to select items and perform an action on the selection. ```jsx -class ResourceListExample extends React.Component { - state = { - selectedItems: [], - }; +function ResourceListWithBulkActionsExample() { + const [selectedItems, setSelectedItems] = useState([]); - handleSelectionChange = (selectedItems) => { - this.setState({selectedItems}); + const resourceName = { + singular: 'customer', + plural: 'customers', }; - renderItem = (item) => { + const items = [ + { + id: 341, + url: 'customers/341', + name: 'Mae Jemison', + location: 'Decatur, USA', + }, + { + id: 256, + url: 'customers/256', + name: 'Ellen Ochoa', + location: 'Los Angeles, USA', + }, + ]; + + const promotedBulkActions = [ + { + content: 'Edit customers', + onAction: () => console.log('Todo: implement bulk edit'), + }, + ]; + + const bulkActions = [ + { + content: 'Add tags', + onAction: () => console.log('Todo: implement bulk add tags'), + }, + { + content: 'Remove tags', + onAction: () => console.log('Todo: implement bulk remove tags'), + }, + { + content: 'Delete customers', + onAction: () => console.log('Todo: implement bulk delete'), + }, + ]; + + return ( + + + + ); + + function renderItem(item) { const {id, url, name, location} = item; const media = ; @@ -185,64 +227,6 @@ class ResourceListExample extends React.Component {
{location}
); - }; - - render() { - const resourceName = { - singular: 'customer', - plural: 'customers', - }; - - const items = [ - { - id: 341, - url: 'customers/341', - name: 'Mae Jemison', - location: 'Decatur, USA', - }, - { - id: 256, - url: 'customers/256', - name: 'Ellen Ochoa', - location: 'Los Angeles, USA', - }, - ]; - - const promotedBulkActions = [ - { - content: 'Edit customers', - onAction: () => console.log('Todo: implement bulk edit'), - }, - ]; - - const bulkActions = [ - { - content: 'Add tags', - onAction: () => console.log('Todo: implement bulk add tags'), - }, - { - content: 'Remove tags', - onAction: () => console.log('Todo: implement bulk remove tags'), - }, - { - content: 'Delete customers', - onAction: () => console.log('Todo: implement bulk delete'), - }, - ]; - - return ( - - - - ); } } ``` @@ -252,16 +236,67 @@ class ResourceListExample extends React.Component { Notifies merchants that list items are being processed. ```jsx -class ResourceListExample extends React.Component { - state = { - selectedItems: [], - }; +function ResourceListWithLoadingExample() { + const [selectedItems, setSelectedItems] = useState([]); - handleSelectionChange = (selectedItems) => { - this.setState({selectedItems}); + const resourceName = { + singular: 'customer', + plural: 'customers', }; - renderItem = (item) => { + const items = [ + { + id: 341, + url: 'customers/341', + name: 'Mae Jemison', + location: 'Decatur, USA', + }, + { + id: 256, + url: 'customers/256', + name: 'Ellen Ochoa', + location: 'Los Angeles, USA', + }, + ]; + + const promotedBulkActions = [ + { + content: 'Edit customers', + onAction: () => console.log('Todo: implement bulk edit'), + }, + ]; + + const bulkActions = [ + { + content: 'Add tags', + onAction: () => console.log('Todo: implement bulk add tags'), + }, + { + content: 'Remove tags', + onAction: () => console.log('Todo: implement bulk remove tags'), + }, + { + content: 'Delete customers', + onAction: () => console.log('Todo: implement bulk delete'), + }, + ]; + + return ( + + + + ); + + function renderItem(item) { const {id, url, name, location} = item; const media = ; @@ -278,65 +313,6 @@ class ResourceListExample extends React.Component {
{location}
); - }; - - render() { - const resourceName = { - singular: 'customer', - plural: 'customers', - }; - - const items = [ - { - id: 341, - url: 'customers/341', - name: 'Mae Jemison', - location: 'Decatur, USA', - }, - { - id: 256, - url: 'customers/256', - name: 'Ellen Ochoa', - location: 'Los Angeles, USA', - }, - ]; - - const promotedBulkActions = [ - { - content: 'Edit customers', - onAction: () => console.log('Todo: implement bulk edit'), - }, - ]; - - const bulkActions = [ - { - content: 'Add tags', - onAction: () => console.log('Todo: implement bulk add tags'), - }, - { - content: 'Remove tags', - onAction: () => console.log('Todo: implement bulk remove tags'), - }, - { - content: 'Delete customers', - onAction: () => console.log('Todo: implement bulk delete'), - }, - ]; - - return ( - - - - ); } } ``` @@ -346,16 +322,49 @@ class ResourceListExample extends React.Component { Allows merchants to change the way the list is sorted by selecting one of several options from a [Select](https://polaris.shopify.com/components/forms/select) control. ```jsx -class ResourceListExample extends React.Component { - state = { - sortValue: 'DATE_MODIFIED_DESC', - }; +function ResourceListWithSortingExample() { + const [sortValue, setSortValue] = useState('DATE_MODIFIED_DESC'); - handleSortChange = (sortValue) => { - this.setState({sortValue}); + const resourceName = { + singular: 'customer', + plural: 'customers', }; - renderItem = (item) => { + const items = [ + { + id: 341, + url: 'customers/341', + name: 'Mae Jemison', + location: 'Decatur, USA', + }, + { + id: 256, + url: 'customers/256', + name: 'Ellen Ochoa', + location: 'Los Angeles, USA', + }, + ]; + + return ( + + { + setSortValue(selected); + console.log(`Sort option changed to ${selected}.`); + }} + /> + + ); + + function renderItem(item) { const {id, url, name, location} = item; const media = ; @@ -372,47 +381,6 @@ class ResourceListExample extends React.Component {
{location}
); - }; - - render() { - const resourceName = { - singular: 'customer', - plural: 'customers', - }; - - const items = [ - { - id: 341, - url: 'customers/341', - name: 'Mae Jemison', - location: 'Decatur, USA', - }, - { - id: 256, - url: 'customers/256', - name: 'Ellen Ochoa', - location: 'Los Angeles, USA', - }, - ]; - - return ( - - { - this.setState({sortValue: selected}); - console.log(`Sort option changed to ${selected}.`); - }} - /> - - ); } } ``` @@ -422,8 +390,39 @@ class ResourceListExample extends React.Component { Allows merchants to add an alternate tool in the current sort option location when sort may not be the most relevant action for the current list. ```jsx -class ResourceListExample extends React.Component { - renderItem = (item) => { +function ResourceListWithAlternateToolExample() { + const resourceName = { + singular: 'Customer', + plural: 'Customers', + }; + + const items = [ + { + id: 341, + url: 'customers/341', + name: 'Mae Jemison', + location: 'Decatur, USA', + }, + { + id: 256, + url: 'customers/256', + name: 'Ellen Ochoa', + location: 'Los Angeles, USA', + }, + ]; + + return ( + + Email customers} + /> + + ); + + function renderItem(item) { const {id, url, name, location} = item; const media = ; @@ -440,39 +439,6 @@ class ResourceListExample extends React.Component {
{location}
); - }; - - render() { - const resourceName = { - singular: 'Customer', - plural: 'Customers', - }; - - const items = [ - { - id: 341, - url: 'customers/341', - name: 'Mae Jemison', - location: 'Decatur, USA', - }, - { - id: 256, - url: 'customers/256', - name: 'Ellen Ochoa', - location: 'Los Angeles, USA', - }, - ]; - - return ( - - Email customers} - /> - - ); } } ``` @@ -482,13 +448,98 @@ class ResourceListExample extends React.Component { Allows merchants to narrow the resource list to a subset of the original items. ```jsx -class ResourceListExample extends React.Component { - state = { - taggedWith: 'VIP', - queryValue: null, +function ResourceListWithFilteringExample() { + const [taggedWith, setTaggedWith] = useState('VIP'); + const [queryValue, setQueryValue] = useState(null); + + const handleTaggedWithChange = useCallback( + (value) => setTaggedWith(value), + [], + ); + const handleQueryValueChange = useCallback( + (value) => setQueryValue(value), + [], + ); + const handleTaggedWithRemove = useCallback(() => setTaggedWith(null), []); + const handleQueryValueRemove = useCallback(() => setQueryValue(null), []); + const handleClearAll = useCallback(() => { + handleTaggedWithRemove(); + handleQueryValueRemove(); + }, [handleQueryValueRemove, handleTaggedWithRemove]); + + const resourceName = { + singular: 'customer', + plural: 'customers', }; - renderItem = (item) => { + const items = [ + { + id: 341, + url: 'customers/341', + name: 'Mae Jemison', + location: 'Decatur, USA', + }, + { + id: 256, + url: 'customers/256', + name: 'Ellen Ochoa', + location: 'Los Angeles, USA', + }, + ]; + + const filters = [ + { + key: 'taggedWith', + label: 'Tagged with', + filter: ( + + ), + shortcut: true, + }, + ]; + + const appliedFilters = !isEmpty(taggedWith) + ? [ + { + key: 'taggedWith', + label: disambiguateLabel('taggedWith', taggedWith), + onRemove: handleTaggedWithRemove, + }, + ] + : []; + + const filterControl = ( + +
+ +
+
+ ); + + return ( + + + + ); + + function renderItem(item) { const {id, url, name, location} = item; const media = ; @@ -500,117 +551,23 @@ class ResourceListExample extends React.Component {
{location}
); - }; - - render() { - const {taggedWith, queryValue} = this.state; - const resourceName = { - singular: 'customer', - plural: 'customers', - }; - - const items = [ - { - id: 341, - url: 'customers/341', - name: 'Mae Jemison', - location: 'Decatur, USA', - }, - { - id: 256, - url: 'customers/256', - name: 'Ellen Ochoa', - location: 'Los Angeles, USA', - }, - ]; - - const filters = [ - { - key: 'taggedWith', - label: 'Tagged with', - filter: ( - - ), - shortcut: true, - }, - ]; - - const appliedFilters = Object.keys(this.state) - .filter((key) => !isEmpty(this.state[key]) && key === 'taggedWith') - .map((key) => { - return { - key, - label: disambiguateLabel(key, this.state[key]), - onRemove: this.handleRemove, - }; - }); - - const filterControl = ( - -
- -
-
- ); - - return ( - - - - ); } - handleChange = (key) => (value) => { - this.setState({[key]: value}); - }; - - handleRemove = (key) => { - this.setState({[key]: null}); - }; - - handleQueryClear = () => { - this.setState({queryValue: null}); - }; - - handleClearAll = () => { - this.setState({ - taggedWith: null, - queryValue: null, - }); - }; -} - -function disambiguateLabel(key, value) { - switch (key) { - case 'taggedWith': - return `Tagged with ${value}`; - default: - return value; + function disambiguateLabel(key, value) { + switch (key) { + case 'taggedWith': + return `Tagged with ${value}`; + default: + return value; + } } -} -function isEmpty(value) { - if (Array.isArray(value)) { - return value.length === 0; - } else { - return value === '' || value == null; + function isEmpty(value) { + if (Array.isArray(value)) { + return value.length === 0; + } else { + return value === '' || value == null; + } } } ``` @@ -733,16 +690,91 @@ Use persistent shortcut actions in rare cases when the action cannot be made ava Allows merchants to select or deselect multiple items at once. ```jsx -class ResourceListExample extends React.Component { - state = { - selectedItems: [], - }; +function ResourceListExample() { + const [selectedItems, setSelectedItems] = useState([]); - handleSelectionChange = (selectedItems) => { - this.setState({selectedItems}); + const resourceName = { + singular: 'customer', + plural: 'customers', }; - renderItem = (item, _, index) => { + const items = [ + { + id: 231, + url: 'customers/231', + name: 'Mae Jemison', + location: 'Decatur, USA', + }, + { + id: 246, + url: 'customers/246', + name: 'Ellen Ochoa', + location: 'Los Angeles, USA', + }, + { + id: 276, + url: 'customers/276', + name: 'Joe Smith', + location: 'Arizona, USA', + }, + { + id: 349, + url: 'customers/349', + name: 'Haden Jerado', + location: 'Decatur, USA', + }, + { + id: 419, + url: 'customers/419', + name: 'Tom Thommas', + location: 'Florida, USA', + }, + { + id: 516, + url: 'customers/516', + name: 'Emily Amrak', + location: 'Texas, USA', + }, + ]; + + const promotedBulkActions = [ + { + content: 'Edit customers', + onAction: () => console.log('Todo: implement bulk edit'), + }, + ]; + + const bulkActions = [ + { + content: 'Add tags', + onAction: () => console.log('Todo: implement bulk add tags'), + }, + { + content: 'Remove tags', + onAction: () => console.log('Todo: implement bulk remove tags'), + }, + { + content: 'Delete customers', + onAction: () => console.log('Todo: implement bulk delete'), + }, + ]; + + return ( + + + + ); + + function renderItem(item, _, index) { const {id, url, name, location} = item; const media = ; @@ -760,94 +792,11 @@ class ResourceListExample extends React.Component {
{location}
); - }; - - render() { - const resourceName = { - singular: 'customer', - plural: 'customers', - }; - - const items = [ - { - id: 231, - url: 'customers/231', - name: 'Mae Jemison', - location: 'Decatur, USA', - }, - { - id: 246, - url: 'customers/246', - name: 'Ellen Ochoa', - location: 'Los Angeles, USA', - }, - { - id: 276, - url: 'customers/276', - name: 'Joe Smith', - location: 'Arizona, USA', - }, - { - id: 349, - url: 'customers/349', - name: 'Haden Jerado', - location: 'Decatur, USA', - }, - { - id: 419, - url: 'customers/419', - name: 'Tom Thommas', - location: 'Florida, USA', - }, - { - id: 516, - url: 'customers/516', - name: 'Emily Amrak', - location: 'Texas, USA', - }, - ]; - - const promotedBulkActions = [ - { - content: 'Edit customers', - onAction: () => console.log('Todo: implement bulk edit'), - }, - ]; - - const bulkActions = [ - { - content: 'Add tags', - onAction: () => console.log('Todo: implement bulk add tags'), - }, - { - content: 'Remove tags', - onAction: () => console.log('Todo: implement bulk remove tags'), - }, - { - content: 'Delete customers', - onAction: () => console.log('Todo: implement bulk delete'), - }, - ]; - - return ( - - - - ); } -} -function resolveItemIds({id}) { - return id; + function resolveItemIds({id}) { + return id; + } } ``` @@ -856,15 +805,137 @@ function resolveItemIds({id}) { Use as a broad example that includes most props available to resource list. ```jsx -class ResourceListExample extends React.Component { - state = { - selectedItems: [], - sortValue: 'DATE_MODIFIED_DESC', - taggedWith: 'VIP', - queryValue: null, +function ResourceListExample() { + const [selectedItems, setSelectedItems] = useState([]); + const [sortValue, setSortValue] = useState('DATE_MODIFIED_DESC'); + const [taggedWith, setTaggedWith] = useState('VIP'); + const [queryValue, setQueryValue] = useState(null); + + const handleTaggedWithChange = useCallback( + (value) => setTaggedWith(value), + [], + ); + const handleQueryValueChange = useCallback( + (value) => setQueryValue(value), + [], + ); + const handleTaggedWithRemove = useCallback(() => setTaggedWith(null), []); + const handleQueryValueRemove = useCallback(() => setQueryValue(null), []); + const handleClearAll = useCallback(() => { + handleTaggedWithRemove(); + handleQueryValueRemove(); + }, [handleQueryValueRemove, handleTaggedWithRemove]); + + const resourceName = { + singular: 'customer', + plural: 'customers', }; - renderItem = (item) => { + const items = [ + { + id: 341, + url: 'customers/341', + name: 'Mae Jemison', + location: 'Decatur, USA', + latestOrderUrl: 'orders/1456', + }, + { + id: 256, + url: 'customers/256', + name: 'Ellen Ochoa', + location: 'Los Angeles, USA', + latestOrderUrl: 'orders/1457', + }, + ]; + + const promotedBulkActions = [ + { + content: 'Edit customers', + onAction: () => console.log('Todo: implement bulk edit'), + }, + ]; + + const bulkActions = [ + { + content: 'Add tags', + onAction: () => console.log('Todo: implement bulk add tags'), + }, + { + content: 'Remove tags', + onAction: () => console.log('Todo: implement bulk remove tags'), + }, + { + content: 'Delete customers', + onAction: () => console.log('Todo: implement bulk delete'), + }, + ]; + + const filters = [ + { + key: 'taggedWith', + label: 'Tagged with', + filter: ( + + ), + shortcut: true, + }, + ]; + + const appliedFilters = !isEmpty(taggedWith) + ? [ + { + key: 'taggedWith', + label: disambiguateLabel('taggedWith', taggedWith), + onRemove: handleTaggedWithRemove, + }, + ] + : []; + + const filterControl = ( + +
+ +
+
+ ); + + return ( + + { + setSortValue(selected); + console.log(`Sort option changed to ${selected}.`); + }} + filterControl={filterControl} + /> + + ); + + function renderItem(item) { const {id, url, name, location, latestOrderUrl} = item; const media = ; const shortcutActions = latestOrderUrl @@ -885,158 +956,23 @@ class ResourceListExample extends React.Component {
{location}
); - }; - - render() { - const {taggedWith, queryValue} = this.state; - const resourceName = { - singular: 'customer', - plural: 'customers', - }; - - const items = [ - { - id: 341, - url: 'customers/341', - name: 'Mae Jemison', - location: 'Decatur, USA', - latestOrderUrl: 'orders/1456', - }, - { - id: 256, - url: 'customers/256', - name: 'Ellen Ochoa', - location: 'Los Angeles, USA', - latestOrderUrl: 'orders/1457', - }, - ]; - - const promotedBulkActions = [ - { - content: 'Edit customers', - onAction: () => console.log('Todo: implement bulk edit'), - }, - ]; - - const bulkActions = [ - { - content: 'Add tags', - onAction: () => console.log('Todo: implement bulk add tags'), - }, - { - content: 'Remove tags', - onAction: () => console.log('Todo: implement bulk remove tags'), - }, - { - content: 'Delete customers', - onAction: () => console.log('Todo: implement bulk delete'), - }, - ]; - - const filters = [ - { - key: 'taggedWith', - label: 'Tagged with', - filter: ( - - ), - shortcut: true, - }, - ]; - - const appliedFilters = Object.keys(this.state) - .filter((key) => !isEmpty(this.state[key]) && key === 'taggedWith') - .map((key) => { - return { - key, - label: disambiguateLabel(key, this.state[key]), - onRemove: this.handleRemove, - }; - }); - - const filterControl = ( - -
- -
-
- ); - - return ( - - { - this.setState({sortValue: selected}); - console.log(`Sort option changed to ${selected}.`); - }} - filterControl={filterControl} - /> - - ); } - handleSelectionChange = (selectedItems) => { - this.setState({selectedItems}); - }; - - handleChange = (key) => (value) => { - this.setState({[key]: value}); - }; - - handleRemove = (key) => { - this.setState({[key]: null}); - }; - - handleQueryClear = () => { - this.setState({queryValue: null}); - }; - - handleClearAll = () => { - this.setState({ - taggedWith: null, - queryValue: null, - }); - }; -} - -function disambiguateLabel(key, value) { - switch (key) { - case 'taggedWith': - return `Tagged with ${value}`; - default: - return value; + function disambiguateLabel(key, value) { + switch (key) { + case 'taggedWith': + return `Tagged with ${value}`; + default: + return value; + } } -} -function isEmpty(value) { - if (Array.isArray(value)) { - return value.length === 0; - } else { - return value === '' || value == null; + function isEmpty(value) { + if (Array.isArray(value)) { + return value.length === 0; + } else { + return value === '' || value == null; + } } } ``` diff --git a/src/components/ResourcePicker/README.md b/src/components/ResourcePicker/README.md index 15c0be911ce..1a8239224e2 100644 --- a/src/components/ResourcePicker/README.md +++ b/src/components/ResourcePicker/README.md @@ -48,25 +48,28 @@ As of v3.17.0, `ResourcePicker` is deprecated. It will be removed in v5.0 as the When you ask for products, the `onSelection` callback is called with an object that has a `selection` key, which will have an array of objects detailing the selected products (even if `allowMultiple` is set to `false`). ```jsx -class EmbeddedAppResourcePickerExample extends React.Component { - state = { - resourcePickerOpen: false, - }; - - render() { - return ( - - { - console.log('Selected products: ', selection); - this.setState({resourcePickerOpen: false}); - }} - onCancel={() => this.setState({resourcePickerOpen: false})} - /> - - ); - } +function EmbeddedAppResourcePickerExample() { + const [active, setActive] = useState(false); + + const handleResourcePickerClose = useCallback(() => setActive(false), []); + + const handleSelection = useCallback( + ({selection}) => { + console.log('Selected products: ', selection); + handleResourcePickerClose(); + }, + [handleResourcePickerClose], + ); + + return ( + + + + ); } ``` diff --git a/src/components/Select/README.md b/src/components/Select/README.md index f4d88240f9a..67f983eff10 100644 --- a/src/components/Select/README.md +++ b/src/components/Select/README.md @@ -99,31 +99,25 @@ Options should: Presents a classic dropdown menu or equivalent picker as determined by merchants’ browsers. ```jsx -class SelectExample extends React.Component { - state = { - selected: 'today', - }; - - handleChange = (newValue) => { - this.setState({selected: newValue}); - }; - - render() { - const options = [ - {label: 'Today', value: 'today'}, - {label: 'Yesterday', value: 'yesterday'}, - {label: 'Last 7 days', value: 'lastWeek'}, - ]; +function SelectExample() { + const [selected, setSelected] = useState('today'); - return ( - + ); } ``` @@ -152,35 +146,29 @@ The Android menu is similar in behavior to the web dropdown. Use only for cases where the select must fit on a single line, such as in a toolbar. ```jsx -class InlineLabelExample extends React.Component { - state = { - selected: 'newestUpdate', - }; - - handleChange = (newValue) => { - this.setState({selected: newValue}); - }; - - render() { - const options = [ - {label: 'Newest update', value: 'newestUpdate'}, - {label: 'Oldest update', value: 'oldestUpdate'}, - {label: 'Most spent', value: 'mostSpent'}, - {label: 'Most orders', value: 'mostOrders'}, - {label: 'Last name A–Z', value: 'lastNameAlpha'}, - {label: 'Last name Z–A', value: 'lastNameReverseAlpha'}, - ]; - - return ( - + ); } ``` @@ -219,26 +207,20 @@ Use for selections that aren’t currently available. The surrounding interface Use to let merchants know if there’s a problem with their selection. For selects, a selection is typically invalid only when using a placeholder option (“Select”) and no other selection has been made. ```jsx -class ValidationErrorExample extends React.Component { - state = { - value: '', - }; - - handleChange = (value) => { - this.setState({value}); - }; - - render() { - return ( - + ); } ``` @@ -257,51 +239,44 @@ To render an invalid select and its validation error separately: - Use an [inline error component](https://polaris.shopify.com/components/forms/inline-error) to describe the invalid select input and set its `fieldID` prop to the same unique identifier used for the text field `id` ```jsx -class SeparateValidationErrorExample extends React.Component { - state = { - weight: '12', - unit: '', - }; - - render() { - const {weight, unit} = this.state; - const unitSelectID = 'unit'; - const errorMessage = this.generateErrorMessage(); - const formGroupMarkup = ( - - - - - + + + + + ); + + return {formGroupMarkup}; + + function generateErrorMessage() { const weightError = !weight && unit ? 'The numeric weight of the product ' : ''; const unitError = @@ -321,7 +296,7 @@ class SeparateValidationErrorExample extends React.Component { ); - }; + } } ```