Skip to content

Commit 1984b4e

Browse files
committed
chore(Label|List): use React.forwardRef() (#4252)
1 parent 2f50326 commit 1984b4e

19 files changed

+306
-290
lines changed

src/elements/Label/Label.js

Lines changed: 86 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import cx from 'clsx'
22
import _ from 'lodash'
33
import PropTypes from 'prop-types'
4-
import React, { Component } from 'react'
4+
import React from 'react'
55

66
import {
77
childrenUtils,
@@ -13,6 +13,7 @@ import {
1313
useKeyOnly,
1414
useKeyOrValueAndKey,
1515
useValueAndKey,
16+
useEventCallback,
1617
} from '../../lib'
1718
import Icon from '../Icon/Icon'
1819
import Image from '../Image/Image'
@@ -22,100 +23,95 @@ import LabelGroup from './LabelGroup'
2223
/**
2324
* A label displays content classification.
2425
*/
25-
export default class Label extends Component {
26-
handleClick = (e) => {
27-
const { onClick } = this.props
28-
29-
if (onClick) onClick(e, this.props)
30-
}
31-
32-
handleIconOverrides = (predefinedProps) => ({
33-
onClick: (e) => {
34-
_.invoke(predefinedProps, 'onClick', e)
35-
_.invoke(this.props, 'onRemove', e, this.props)
36-
},
26+
const Label = React.forwardRef(function (props, ref) {
27+
const {
28+
active,
29+
attached,
30+
basic,
31+
children,
32+
circular,
33+
className,
34+
color,
35+
content,
36+
corner,
37+
detail,
38+
empty,
39+
floating,
40+
horizontal,
41+
icon,
42+
image,
43+
onRemove,
44+
pointing,
45+
prompt,
46+
removeIcon,
47+
ribbon,
48+
size,
49+
tag,
50+
} = props
51+
52+
const pointingClass =
53+
(pointing === true && 'pointing') ||
54+
((pointing === 'left' || pointing === 'right') && `${pointing} pointing`) ||
55+
((pointing === 'above' || pointing === 'below') && `pointing ${pointing}`)
56+
57+
const classes = cx(
58+
'ui',
59+
color,
60+
pointingClass,
61+
size,
62+
useKeyOnly(active, 'active'),
63+
useKeyOnly(basic, 'basic'),
64+
useKeyOnly(circular, 'circular'),
65+
useKeyOnly(empty, 'empty'),
66+
useKeyOnly(floating, 'floating'),
67+
useKeyOnly(horizontal, 'horizontal'),
68+
useKeyOnly(image === true, 'image'),
69+
useKeyOnly(prompt, 'prompt'),
70+
useKeyOnly(tag, 'tag'),
71+
useKeyOrValueAndKey(corner, 'corner'),
72+
useKeyOrValueAndKey(ribbon, 'ribbon'),
73+
useValueAndKey(attached, 'attached'),
74+
'label',
75+
className,
76+
)
77+
const rest = getUnhandledProps(Label, props)
78+
const ElementType = getElementType(Label, props)
79+
80+
const handleClick = useEventCallback((e) => {
81+
_.invoke(props, 'onClick', e, props)
3782
})
3883

39-
render() {
40-
const {
41-
active,
42-
attached,
43-
basic,
44-
children,
45-
circular,
46-
className,
47-
color,
48-
content,
49-
corner,
50-
detail,
51-
empty,
52-
floating,
53-
horizontal,
54-
icon,
55-
image,
56-
onRemove,
57-
pointing,
58-
prompt,
59-
removeIcon,
60-
ribbon,
61-
size,
62-
tag,
63-
} = this.props
64-
65-
const pointingClass =
66-
(pointing === true && 'pointing') ||
67-
((pointing === 'left' || pointing === 'right') && `${pointing} pointing`) ||
68-
((pointing === 'above' || pointing === 'below') && `pointing ${pointing}`)
69-
70-
const classes = cx(
71-
'ui',
72-
color,
73-
pointingClass,
74-
size,
75-
useKeyOnly(active, 'active'),
76-
useKeyOnly(basic, 'basic'),
77-
useKeyOnly(circular, 'circular'),
78-
useKeyOnly(empty, 'empty'),
79-
useKeyOnly(floating, 'floating'),
80-
useKeyOnly(horizontal, 'horizontal'),
81-
useKeyOnly(image === true, 'image'),
82-
useKeyOnly(prompt, 'prompt'),
83-
useKeyOnly(tag, 'tag'),
84-
useKeyOrValueAndKey(corner, 'corner'),
85-
useKeyOrValueAndKey(ribbon, 'ribbon'),
86-
useValueAndKey(attached, 'attached'),
87-
'label',
88-
className,
89-
)
90-
const rest = getUnhandledProps(Label, this.props)
91-
const ElementType = getElementType(Label, this.props)
92-
93-
if (!childrenUtils.isNil(children)) {
94-
return (
95-
<ElementType {...rest} className={classes} onClick={this.handleClick}>
96-
{children}
97-
</ElementType>
98-
)
99-
}
100-
101-
const removeIconShorthand = _.isUndefined(removeIcon) ? 'delete' : removeIcon
102-
84+
if (!childrenUtils.isNil(children)) {
10385
return (
104-
<ElementType className={classes} onClick={this.handleClick} {...rest}>
105-
{Icon.create(icon, { autoGenerateKey: false })}
106-
{typeof image !== 'boolean' && Image.create(image, { autoGenerateKey: false })}
107-
{content}
108-
{LabelDetail.create(detail, { autoGenerateKey: false })}
109-
{onRemove &&
110-
Icon.create(removeIconShorthand, {
111-
autoGenerateKey: false,
112-
overrideProps: this.handleIconOverrides,
113-
})}
86+
<ElementType {...rest} className={classes} onClick={handleClick} ref={ref}>
87+
{children}
11488
</ElementType>
11589
)
11690
}
117-
}
11891

92+
const removeIconShorthand = _.isUndefined(removeIcon) ? 'delete' : removeIcon
93+
94+
return (
95+
<ElementType {...rest} className={classes} onClick={handleClick} ref={ref}>
96+
{Icon.create(icon, { autoGenerateKey: false })}
97+
{typeof image !== 'boolean' && Image.create(image, { autoGenerateKey: false })}
98+
{content}
99+
{LabelDetail.create(detail, { autoGenerateKey: false })}
100+
{onRemove &&
101+
Icon.create(removeIconShorthand, {
102+
autoGenerateKey: false,
103+
overrideProps: (predefinedProps) => ({
104+
onClick: (e) => {
105+
_.invoke(predefinedProps, 'onClick', e)
106+
_.invoke(props, 'onRemove', e, props)
107+
},
108+
}),
109+
})}
110+
</ElementType>
111+
)
112+
})
113+
114+
Label.displayName = 'Label'
119115
Label.propTypes = {
120116
/** An element type to render as (string or function). */
121117
as: PropTypes.elementType,
@@ -214,3 +210,5 @@ Label.Detail = LabelDetail
214210
Label.Group = LabelGroup
215211

216212
Label.create = createShorthandFactory(Label, (value) => ({ content: value }))
213+
214+
export default Label

src/elements/Label/LabelDetail.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,21 @@ import {
1010
getUnhandledProps,
1111
} from '../../lib'
1212

13-
function LabelDetail(props) {
13+
const LabelDetail = React.forwardRef(function (props, ref) {
1414
const { children, className, content } = props
15+
1516
const classes = cx('detail', className)
1617
const rest = getUnhandledProps(LabelDetail, props)
1718
const ElementType = getElementType(LabelDetail, props)
1819

1920
return (
20-
<ElementType {...rest} className={classes}>
21+
<ElementType {...rest} className={classes} ref={ref}>
2122
{childrenUtils.isNil(children) ? content : children}
2223
</ElementType>
2324
)
24-
}
25+
})
2526

27+
LabelDetail.displayName = 'LabelDetail'
2628
LabelDetail.propTypes = {
2729
/** An element type to render as (string or function). */
2830
as: PropTypes.elementType,

src/elements/Label/LabelGroup.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
/**
1515
* A label can be grouped.
1616
*/
17-
function LabelGroup(props) {
17+
const LabelGroup = React.forwardRef(function (props, ref) {
1818
const { children, circular, className, color, content, size, tag } = props
1919

2020
const classes = cx(
@@ -30,12 +30,13 @@ function LabelGroup(props) {
3030
const ElementType = getElementType(LabelGroup, props)
3131

3232
return (
33-
<ElementType {...rest} className={classes}>
33+
<ElementType {...rest} className={classes} ref={ref}>
3434
{childrenUtils.isNil(children) ? content : children}
3535
</ElementType>
3636
)
37-
}
37+
})
3838

39+
LabelGroup.displayName = 'LabelGroup'
3940
LabelGroup.propTypes = {
4041
/** An element type to render as (string or function). */
4142
as: PropTypes.elementType,

0 commit comments

Comments
 (0)