Skip to content

Commit 030301f

Browse files
committed
chore(Message): use React.forwardRef() (#4251)
1 parent 8fb167c commit 030301f

File tree

10 files changed

+99
-87
lines changed

10 files changed

+99
-87
lines changed

src/collections/Message/Message.js

Lines changed: 74 additions & 75 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,
@@ -12,6 +12,7 @@ import {
1212
SUI,
1313
useKeyOnly,
1414
useKeyOrValueAndKey,
15+
useEventCallback,
1516
} from '../../lib'
1617
import Icon from '../../elements/Icon'
1718
import MessageContent from './MessageContent'
@@ -23,86 +24,82 @@ import MessageItem from './MessageItem'
2324
* A message displays information that explains nearby content.
2425
* @see Form
2526
*/
26-
export default class Message extends Component {
27-
handleDismiss = (e) => {
28-
const { onDismiss } = this.props
29-
30-
if (onDismiss) onDismiss(e, this.props)
31-
}
32-
33-
render() {
34-
const {
35-
attached,
36-
children,
37-
className,
38-
color,
39-
compact,
40-
content,
41-
error,
42-
floating,
43-
header,
44-
hidden,
45-
icon,
46-
info,
47-
list,
48-
negative,
49-
onDismiss,
50-
positive,
51-
size,
52-
success,
53-
visible,
54-
warning,
55-
} = this.props
56-
57-
const classes = cx(
58-
'ui',
59-
color,
60-
size,
61-
useKeyOnly(compact, 'compact'),
62-
useKeyOnly(error, 'error'),
63-
useKeyOnly(floating, 'floating'),
64-
useKeyOnly(hidden, 'hidden'),
65-
useKeyOnly(icon, 'icon'),
66-
useKeyOnly(info, 'info'),
67-
useKeyOnly(negative, 'negative'),
68-
useKeyOnly(positive, 'positive'),
69-
useKeyOnly(success, 'success'),
70-
useKeyOnly(visible, 'visible'),
71-
useKeyOnly(warning, 'warning'),
72-
useKeyOrValueAndKey(attached, 'attached'),
73-
'message',
74-
className,
75-
)
76-
77-
const dismissIcon = onDismiss && <Icon name='close' onClick={this.handleDismiss} />
78-
const rest = getUnhandledProps(Message, this.props)
79-
const ElementType = getElementType(Message, this.props)
80-
81-
if (!childrenUtils.isNil(children)) {
82-
return (
83-
<ElementType {...rest} className={classes}>
84-
{dismissIcon}
85-
{children}
86-
</ElementType>
87-
)
88-
}
89-
27+
const Message = React.forwardRef(function (props, ref) {
28+
const {
29+
attached,
30+
children,
31+
className,
32+
color,
33+
compact,
34+
content,
35+
error,
36+
floating,
37+
header,
38+
hidden,
39+
icon,
40+
info,
41+
list,
42+
negative,
43+
onDismiss,
44+
positive,
45+
size,
46+
success,
47+
visible,
48+
warning,
49+
} = props
50+
51+
const classes = cx(
52+
'ui',
53+
color,
54+
size,
55+
useKeyOnly(compact, 'compact'),
56+
useKeyOnly(error, 'error'),
57+
useKeyOnly(floating, 'floating'),
58+
useKeyOnly(hidden, 'hidden'),
59+
useKeyOnly(icon, 'icon'),
60+
useKeyOnly(info, 'info'),
61+
useKeyOnly(negative, 'negative'),
62+
useKeyOnly(positive, 'positive'),
63+
useKeyOnly(success, 'success'),
64+
useKeyOnly(visible, 'visible'),
65+
useKeyOnly(warning, 'warning'),
66+
useKeyOrValueAndKey(attached, 'attached'),
67+
'message',
68+
className,
69+
)
70+
const rest = getUnhandledProps(Message, props)
71+
const ElementType = getElementType(Message, props)
72+
73+
const handleDismiss = useEventCallback((e) => {
74+
_.invoke(props, 'onDismiss', e, props)
75+
})
76+
const dismissIcon = onDismiss && <Icon name='close' onClick={handleDismiss} />
77+
78+
if (!childrenUtils.isNil(children)) {
9079
return (
91-
<ElementType {...rest} className={classes}>
80+
<ElementType {...rest} className={classes} ref={ref}>
9281
{dismissIcon}
93-
{Icon.create(icon, { autoGenerateKey: false })}
94-
{(!_.isNil(header) || !_.isNil(content) || !_.isNil(list)) && (
95-
<MessageContent>
96-
{MessageHeader.create(header, { autoGenerateKey: false })}
97-
{MessageList.create(list, { autoGenerateKey: false })}
98-
{createHTMLParagraph(content, { autoGenerateKey: false })}
99-
</MessageContent>
100-
)}
82+
{children}
10183
</ElementType>
10284
)
10385
}
104-
}
10586

87+
return (
88+
<ElementType {...rest} className={classes} ref={ref}>
89+
{dismissIcon}
90+
{Icon.create(icon, { autoGenerateKey: false })}
91+
{(!_.isNil(header) || !_.isNil(content) || !_.isNil(list)) && (
92+
<MessageContent>
93+
{MessageHeader.create(header, { autoGenerateKey: false })}
94+
{MessageList.create(list, { autoGenerateKey: false })}
95+
{createHTMLParagraph(content, { autoGenerateKey: false })}
96+
</MessageContent>
97+
)}
98+
</ElementType>
99+
)
100+
})
101+
102+
Message.displayName = 'Message'
106103
Message.propTypes = {
107104
/** An element type to render as (string or function). */
108105
as: PropTypes.elementType,
@@ -178,3 +175,5 @@ Message.Content = MessageContent
178175
Message.Header = MessageHeader
179176
Message.List = MessageList
180177
Message.Item = MessageItem
178+
179+
export default Message

src/collections/Message/MessageContent.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,20 @@ import { childrenUtils, customPropTypes, getElementType, getUnhandledProps } fro
77
/**
88
* A message can contain a content.
99
*/
10-
function MessageContent(props) {
10+
const MessageContent = React.forwardRef(function (props, ref) {
1111
const { children, className, content } = props
1212
const classes = cx('content', className)
1313
const rest = getUnhandledProps(MessageContent, props)
1414
const ElementType = getElementType(MessageContent, props)
1515

1616
return (
17-
<ElementType {...rest} className={classes}>
17+
<ElementType {...rest} className={classes} ref={ref}>
1818
{childrenUtils.isNil(children) ? content : children}
1919
</ElementType>
2020
)
21-
}
21+
})
2222

23+
MessageContent.displayName = 'MessageContent'
2324
MessageContent.propTypes = {
2425
/** An element type to render as (string or function). */
2526
as: PropTypes.elementType,

src/collections/Message/MessageHeader.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,21 @@ import {
1313
/**
1414
* A message can contain a header.
1515
*/
16-
function MessageHeader(props) {
16+
const MessageHeader = React.forwardRef(function (props, ref) {
1717
const { children, className, content } = props
18+
1819
const classes = cx('header', className)
1920
const rest = getUnhandledProps(MessageHeader, props)
2021
const ElementType = getElementType(MessageHeader, props)
2122

2223
return (
23-
<ElementType {...rest} className={classes}>
24+
<ElementType {...rest} className={classes} ref={ref}>
2425
{childrenUtils.isNil(children) ? content : children}
2526
</ElementType>
2627
)
27-
}
28+
})
2829

30+
MessageHeader.displayName = 'MessageHeader'
2931
MessageHeader.propTypes = {
3032
/** An element type to render as (string or function). */
3133
as: PropTypes.elementType,

src/collections/Message/MessageItem.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,21 @@ import {
1313
/**
1414
* A message list can contain an item.
1515
*/
16-
function MessageItem(props) {
16+
const MessageItem = React.forwardRef(function (props, ref) {
1717
const { children, className, content } = props
18+
1819
const classes = cx('content', className)
1920
const rest = getUnhandledProps(MessageItem, props)
2021
const ElementType = getElementType(MessageItem, props)
2122

2223
return (
23-
<ElementType {...rest} className={classes}>
24+
<ElementType {...rest} className={classes} ref={ref}>
2425
{childrenUtils.isNil(children) ? content : children}
2526
</ElementType>
2627
)
27-
}
28+
})
2829

30+
MessageItem.displayName = 'MessageItem'
2931
MessageItem.propTypes = {
3032
/** An element type to render as (string or function). */
3133
as: PropTypes.elementType,

src/collections/Message/MessageList.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,21 @@ import MessageItem from './MessageItem'
1515
/**
1616
* A message can contain a list of items.
1717
*/
18-
function MessageList(props) {
18+
const MessageList = React.forwardRef(function (props, ref) {
1919
const { children, className, items } = props
20+
2021
const classes = cx('list', className)
2122
const rest = getUnhandledProps(MessageList, props)
2223
const ElementType = getElementType(MessageList, props)
2324

2425
return (
25-
<ElementType {...rest} className={classes}>
26+
<ElementType {...rest} className={classes} ref={ref}>
2627
{childrenUtils.isNil(children) ? _.map(items, MessageItem.create) : children}
2728
</ElementType>
2829
)
29-
}
30+
})
3031

32+
MessageList.displayName = 'MessageList'
3133
MessageList.propTypes = {
3234
/** An element type to render as (string or function). */
3335
as: PropTypes.elementType,

test/specs/collections/Message/Message-test.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import { sandbox } from 'test/utils'
1111

1212
describe('Message', () => {
1313
common.isConformant(Message)
14+
common.forwardsRef(Message)
15+
common.forwardsRef(Message, { requiredProps: { children: <span /> } })
1416
common.hasSubcomponents(Message, [MessageContent, MessageHeader, MessageList])
1517
common.hasUIClassName(Message)
1618
common.rendersChildren(Message, {

test/specs/collections/Message/MessageContent-test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as common from 'test/specs/commonTests'
44

55
describe('MessageContent', () => {
66
common.isConformant(MessageContent)
7+
common.forwardsRef(MessageContent)
78
common.rendersChildren(MessageContent)
89

910
it('renders an div tag', () => {

test/specs/collections/Message/MessageHeader-test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import * as common from 'test/specs/commonTests'
55

66
describe('MessageHeader', () => {
77
common.isConformant(MessageHeader)
8+
common.forwardsRef(MessageHeader)
89
common.implementsCreateMethod(MessageHeader)
910
common.rendersChildren(MessageHeader)
1011

test/specs/collections/Message/MessageItem-test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as common from 'test/specs/commonTests'
44

55
describe('MessageItem', () => {
66
common.isConformant(MessageItem)
7+
common.forwardsRef(MessageItem, { tagName: 'li' })
78
common.implementsCreateMethod(MessageItem)
89
common.rendersChildren(MessageItem)
910

test/specs/collections/Message/MessageList-test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as common from 'test/specs/commonTests'
44

55
describe('MessageList', () => {
66
common.isConformant(MessageList)
7+
common.forwardsRef(MessageList, { tagName: 'ul' })
78
common.implementsCreateMethod(MessageList)
89
common.rendersChildren(MessageList, {
910
rendersContent: false,

0 commit comments

Comments
 (0)