@@ -21,6 +21,7 @@ import { getShorthandValue } from './helpers/getShorthandValue'
21
21
import { getSplitStyles , useSplitStyles } from './helpers/getSplitStyles'
22
22
import { log } from './helpers/log'
23
23
import { mergeProps } from './helpers/mergeProps'
24
+ import { objectIdentityKey } from './helpers/objectIdentityKey'
24
25
import { setElementProps } from './helpers/setElementProps'
25
26
import { subscribeToContextGroup } from './helpers/subscribeToContextGroup'
26
27
import { themeable } from './helpers/themeable'
@@ -425,9 +426,8 @@ export function createComponent<
425
426
return groupContextParent
426
427
}
427
428
428
- // TODO this shouldn't be in useMemo
429
- stateRef . current . group ?. listeners . clear ( )
430
429
const listeners = new Set < GroupStateListener > ( )
430
+ stateRef . current . group ?. listeners ?. clear ( )
431
431
stateRef . current . group = {
432
432
listeners,
433
433
emit ( state ) {
@@ -635,14 +635,16 @@ export function createComponent<
635
635
debugProp
636
636
)
637
637
638
+ const isPassthrough = ! splitStyles
639
+
638
640
// splitStyles === null === passThrough
639
641
640
642
const groupContext = groupName ? allGroupContexts ?. [ groupName ] || null : null
641
643
642
644
// one tiny mutation 🙏 get width/height optimistically from raw values if possible
643
645
// if set hardcoded it avoids extra renders
644
646
if (
645
- splitStyles &&
647
+ ! isPassthrough &&
646
648
groupContext &&
647
649
// avoids onLayout if we don't need it
648
650
props . containerType !== 'normal'
@@ -661,7 +663,7 @@ export function createComponent<
661
663
// avoids re-rendering if animation driver supports it
662
664
// TODO believe we need to set some sort of "pendingState" in case it re-renders
663
665
if (
664
- splitStyles &&
666
+ ! isPassthrough &&
665
667
( hasAnimationProp || groupName ) &&
666
668
animationDriver ?. avoidReRenders
667
669
) {
@@ -670,22 +672,6 @@ export function createComponent<
670
672
stateRef . current . updateStyleListener = ( ) => {
671
673
const updatedState = NextState . get ( stateRef ) || state
672
674
const mediaState = NextMedia . get ( stateRef )
673
- const {
674
- group,
675
- hasDynGroupChildren,
676
- unmounted,
677
- animation,
678
- ...childrenGroupState
679
- } = updatedState
680
-
681
- // update before getting styles
682
- if ( groupContext ) {
683
- notifyGroupSubscribers (
684
- groupContext ,
685
- stateRef . current . group || null ,
686
- childrenGroupState
687
- )
688
- }
689
675
690
676
const nextStyles = getSplitStyles (
691
677
props ,
@@ -707,6 +693,24 @@ export function createComponent<
707
693
useStyleListener ?.( ( nextStyles ?. style || { } ) as any )
708
694
}
709
695
696
+ function updateGroupListeners ( ) {
697
+ const updatedState = NextState . get ( stateRef ) !
698
+ if ( groupContext ) {
699
+ const {
700
+ group,
701
+ hasDynGroupChildren,
702
+ unmounted,
703
+ animation,
704
+ ...childrenGroupState
705
+ } = updatedState
706
+ notifyGroupSubscribers (
707
+ groupContext ,
708
+ stateRef . current . group || null ,
709
+ childrenGroupState
710
+ )
711
+ }
712
+ }
713
+
710
714
// don't change this ever or else you break ComponentContext and cause re-rendering
711
715
componentContext . mediaEmit ||= ( next ) => {
712
716
NextMedia . set ( stateRef , next )
@@ -739,11 +743,15 @@ export function createComponent<
739
743
debugProp &&
740
744
debugProp !== 'profile'
741
745
) {
742
- console . groupCollapsed ( `[⚡️] avoid setState` , next , { updatedState, props } )
746
+ console . groupCollapsed ( `[⚡️] avoid setState` , componentName , next , {
747
+ updatedState,
748
+ props,
749
+ } )
743
750
console . info ( stateRef . current . host )
744
751
console . groupEnd ( )
745
752
}
746
753
754
+ updateGroupListeners ( )
747
755
stateRef . current . updateStyleListener ?.( )
748
756
} else {
749
757
if (
@@ -917,7 +925,7 @@ export function createComponent<
917
925
if ( process . env . NODE_ENV === 'development' && time ) time `destructure`
918
926
919
927
if (
920
- splitStyles &&
928
+ ! isPassthrough &&
921
929
groupContext && // avoids onLayout if we don't need it
922
930
props . containerType !== 'normal'
923
931
) {
@@ -1036,6 +1044,7 @@ export function createComponent<
1036
1044
1037
1045
useIsomorphicLayoutEffect ( ( ) => {
1038
1046
if ( disabled ) return
1047
+
1039
1048
if ( ! pseudoGroups && ! mediaGroups ) return
1040
1049
if ( ! allGroupContexts ) return
1041
1050
return subscribeToContextGroup ( {
@@ -1047,13 +1056,14 @@ export function createComponent<
1047
1056
} , [
1048
1057
allGroupContexts ,
1049
1058
disabled ,
1050
- pseudoGroups ? Object . keys ( [ ... pseudoGroups ] ) . join ( '' ) : 0 ,
1051
- mediaGroups ? Object . keys ( [ ... mediaGroups ] ) . join ( '' ) : 0 ,
1059
+ pseudoGroups ? objectIdentityKey ( pseudoGroups ) : 0 ,
1060
+ mediaGroups ? objectIdentityKey ( mediaGroups ) : 0 ,
1052
1061
] )
1053
1062
1054
1063
const groupEmitter = stateRef . current . group
1055
1064
useIsomorphicLayoutEffect ( ( ) => {
1056
1065
if ( ! groupContext || ! groupEmitter ) return
1066
+
1057
1067
notifyGroupSubscribers ( groupContext , groupEmitter , state )
1058
1068
} , [ groupContext , groupEmitter , state ] )
1059
1069
@@ -1299,8 +1309,7 @@ export function createComponent<
1299
1309
1300
1310
if ( process . env . NODE_ENV === 'development' && time ) time `spaced-as-child`
1301
1311
1302
- // passthrough mode - only pass style display contents, nothing else
1303
- if ( ! splitStyles ) {
1312
+ if ( isPassthrough ) {
1304
1313
content = propsIn . children
1305
1314
elementType = BaseViewComponent
1306
1315
viewProps = {
@@ -1379,7 +1388,7 @@ export function createComponent<
1379
1388
content = (
1380
1389
< span
1381
1390
className = "_dsp_contents"
1382
- { ...( splitStyles && isHydrated && events && getWebEvents ( events ) ) }
1391
+ { ...( ! isPassthrough && isHydrated && events && getWebEvents ( events ) ) }
1383
1392
>
1384
1393
{ content }
1385
1394
</ span >
@@ -1413,7 +1422,7 @@ export function createComponent<
1413
1422
if ( process . env . TAMAGUI_TARGET === 'web' && startedUnhydrated ) {
1414
1423
// breaking rules of hooks but startedUnhydrated NEVER changes
1415
1424
const styleTags = useMemo ( ( ) => {
1416
- if ( ! splitStyles ) return
1425
+ if ( isPassthrough ) return
1417
1426
return getStyleTags ( Object . values ( splitStyles . rulesToInsert ) )
1418
1427
} , [ ] )
1419
1428
// this is only to appease react hydration really
0 commit comments