1- import { Component } from 'react' ;
1+ import { useEffect , useRef , useState } from 'react' ;
22import * as ReactDOM from 'react-dom' ;
33import { canUseDOM } from '../../helpers' ;
44import { AlertGroupInline } from './AlertGroupInline' ;
5+ import { useHasAnimations } from '../../helpers' ;
56
67export interface AlertGroupProps extends Omit < React . HTMLProps < HTMLUListElement > , 'className' > {
78 /** Additional classes added to the AlertGroup */
@@ -26,78 +27,73 @@ export interface AlertGroupProps extends Omit<React.HTMLProps<HTMLUListElement>,
2627 'aria-label' ?: string ;
2728}
2829
29- interface AlertGroupState {
30- container : HTMLElement ;
31- }
32-
33- class AlertGroup extends Component < AlertGroupProps , AlertGroupState > {
34- static displayName = 'AlertGroup' ;
35- state = {
36- container : undefined
37- } as AlertGroupState ;
38-
39- componentDidMount ( ) {
40- const container = document . createElement ( 'div' ) ;
41- const target : HTMLElement = this . getTargetElement ( ) ;
42- this . setState ( { container } ) ;
43- target . appendChild ( container ) ;
44- }
30+ export const AlertGroup : React . FunctionComponent < AlertGroupProps > = ( {
31+ className,
32+ children,
33+ hasAnimations : localHasAnimations ,
34+ isToast,
35+ isLiveRegion,
36+ onOverflowClick,
37+ overflowMessage,
38+ 'aria-label' : ariaLabel ,
4539
46- componentWillUnmount ( ) {
47- const target : HTMLElement = this . getTargetElement ( ) ;
48- if ( this . state . container ) {
49- target . removeChild ( this . state . container ) ;
50- }
51- }
40+ appendTo , // do not pass down to ul
41+ ... props
42+ } : AlertGroupProps ) => {
43+ const containerRef = useRef < HTMLElement | null > ( null ) ;
44+ const [ isContainerReady , setIsContainerReady ] = useState ( false ) ;
45+ const hasAnimations = useHasAnimations ( localHasAnimations ) ;
5246
53- getTargetElement ( ) {
54- const appendTo = this . props . appendTo ;
47+ const getTargetElement = ( ) => {
5548 if ( typeof appendTo === 'function' ) {
5649 return appendTo ( ) ;
5750 }
5851 return appendTo || document . body ;
59- }
52+ } ;
53+
54+ useEffect ( ( ) => {
55+ if ( isToast && canUseDOM ) {
56+ const container = document . createElement ( 'div' ) ;
57+ const target = getTargetElement ( ) ;
58+ containerRef . current = container ;
59+ target . appendChild ( container ) ;
60+ setIsContainerReady ( true ) ;
6061
61- render ( ) {
62- const {
63- className,
64- children,
65- hasAnimations = false ,
66- isToast,
67- isLiveRegion,
68- onOverflowClick,
69- overflowMessage,
70- 'aria-label' : ariaLabel ,
71- // eslint-disable-next-line @typescript-eslint/no-unused-vars
72- appendTo, // do not pass down to ul
73- ...props
74- } = this . props ;
75- const alertGroup = (
76- < AlertGroupInline
77- onOverflowClick = { onOverflowClick }
78- className = { className }
79- isToast = { isToast }
80- isLiveRegion = { isLiveRegion }
81- overflowMessage = { overflowMessage }
82- aria-label = { ariaLabel }
83- hasAnimations = { hasAnimations }
84- { ...props }
85- >
86- { children }
87- </ AlertGroupInline >
88- ) ;
89- if ( ! this . props . isToast ) {
90- return alertGroup ;
62+ return ( ) => {
63+ if ( containerRef . current ) {
64+ target . removeChild ( containerRef . current ) ;
65+ containerRef . current = null ;
66+ }
67+ setIsContainerReady ( false ) ;
68+ } ;
9169 }
70+ } , [ isToast , appendTo ] ) ;
9271
93- const container = this . state . container ;
72+ const alertGroup = (
73+ < AlertGroupInline
74+ onOverflowClick = { onOverflowClick }
75+ className = { className }
76+ isToast = { isToast }
77+ isLiveRegion = { isLiveRegion }
78+ overflowMessage = { overflowMessage }
79+ aria-label = { ariaLabel }
80+ hasAnimations = { hasAnimations }
81+ { ...props }
82+ >
83+ { children }
84+ </ AlertGroupInline >
85+ ) ;
9486
95- if ( ! canUseDOM || ! container ) {
96- return null ;
97- }
87+ if ( ! isToast ) {
88+ return alertGroup ;
89+ }
90+
91+ const container = containerRef . current ;
9892
99- return ReactDOM . createPortal ( alertGroup , container ) ;
93+ if ( ! canUseDOM || ! container || ! isContainerReady ) {
94+ return null ;
10095 }
101- }
10296
103- export { AlertGroup } ;
97+ return ReactDOM . createPortal ( alertGroup , container ) ;
98+ } ;
99+ AlertGroup . displayName = 'AlertGroup' ;
0 commit comments