@@ -20,6 +20,13 @@ const useEffectOrLayoutEffect = isInBrowser ? React.useLayoutEffect : React.useE
2020
2121const noTheme = { }
2222
23+ const reducer = ( prevState , action ) => {
24+ if ( action . type === 'updateSheet' ) {
25+ return action . payload
26+ }
27+ return prevState
28+ }
29+
2330const createUseStyles = < Theme : { } > (styles: Styles< Theme > , options?: HookOptions< Theme > = { } ) => {
2431 const { index = getSheetIndex ( ) , theming, name, ...sheetOptions } = options
2532 const ThemeContext = ( theming && theming . context ) || DefaultThemeContext
@@ -35,75 +42,109 @@ const createUseStyles = <Theme: {}>(styles: Styles<Theme>, options?: HookOptions
3542 const context = React . useContext ( JssContext )
3643 const theme = useTheme ( )
3744
38- const [ sheet , dynamicRules ] = React . useMemo (
45+ const [ state , dispatch ] = React . useReducer ( reducer , null , ( ) => {
46+ const sheet = createStyleSheet ( {
47+ context,
48+ styles,
49+ name,
50+ theme,
51+ index,
52+ sheetOptions
53+ } )
54+
55+ let dynamicRules
56+ let classes
57+ if ( sheet ) {
58+ if ( context . registry ) {
59+ context . registry . add ( sheet )
60+ }
61+ dynamicRules = addDynamicRules ( sheet , data )
62+ classes = getSheetClasses ( sheet , dynamicRules )
63+ }
64+
65+ return {
66+ sheet,
67+ dynamicRules,
68+ classes : classes || { }
69+ }
70+ } )
71+ React . useMemo (
72+ ( ) => {
73+ if ( ! isFirstMount . current ) {
74+ const newSheet = createStyleSheet ( {
75+ context,
76+ styles,
77+ name,
78+ theme,
79+ index,
80+ sheetOptions
81+ } )
82+ const newDynamicRules = newSheet && addDynamicRules ( newSheet , data )
83+ const newClasses = newSheet ? getSheetClasses ( newSheet , newDynamicRules ) : { }
84+
85+ dispatch ( {
86+ type : 'updateSheet' ,
87+ payload : {
88+ sheet : newSheet ,
89+ dynamicRules : newDynamicRules ,
90+ classes : newClasses
91+ }
92+ } )
93+ }
94+ } ,
95+ [ theme , context ]
96+ )
97+ useEffectOrLayoutEffect (
3998 ( ) => {
40- const newSheet = createStyleSheet ( {
41- context,
42- styles,
43- name,
44- theme,
45- index,
46- sheetOptions
47- } )
48-
49- const newDynamicRules = newSheet ? addDynamicRules ( newSheet , data ) : null
50-
51- if ( newSheet ) {
99+ if ( state . sheet ) {
52100 manageSheet ( {
53101 index,
54102 context,
55- sheet : newSheet ,
103+ sheet : state . sheet ,
56104 theme
57105 } )
58106 }
59107
60- return [ newSheet , newDynamicRules ]
108+ return ( ) => {
109+ const { sheet, dynamicRules} = state
110+
111+ if ( ! sheet ) return
112+
113+ unmanageSheet ( {
114+ index,
115+ context,
116+ sheet,
117+ theme
118+ } )
119+
120+ if ( dynamicRules ) {
121+ removeDynamicRules ( sheet , dynamicRules )
122+ }
123+ }
61124 } ,
62- [ context , theme ]
125+ [ state . sheet ]
63126 )
64127
65128 useEffectOrLayoutEffect (
66129 ( ) => {
67130 // We only need to update the rules on a subsequent update and not in the first mount
68- if ( sheet && dynamicRules && ! isFirstMount . current ) {
69- updateDynamicRules ( data , sheet , dynamicRules )
131+ if ( state . sheet && state . dynamicRules && ! isFirstMount . current ) {
132+ updateDynamicRules ( data , state . sheet , state . dynamicRules )
70133 }
71134 } ,
72135 [ data ]
73136 )
74137
75- useEffectOrLayoutEffect (
76- ( ) =>
77- // cleanup only
78- ( ) => {
79- if ( sheet ) {
80- unmanageSheet ( {
81- index,
82- context,
83- sheet,
84- theme
85- } )
86- }
87-
88- if ( sheet && dynamicRules ) {
89- removeDynamicRules ( sheet , dynamicRules )
90- }
91- } ,
92- [ sheet ]
93- )
94-
95- const classes = sheet && dynamicRules ? getSheetClasses ( sheet , dynamicRules ) : { }
96-
97138 // $FlowFixMe
98- React . useDebugValue ( classes )
139+ React . useDebugValue ( state . classes )
99140 // $FlowFixMe
100141 React . useDebugValue ( theme === noTheme ? 'No theme' : theme )
101142
102143 React . useEffect ( ( ) => {
103144 isFirstMount . current = false
104145 } )
105146
106- return classes
147+ return state . classes
107148 }
108149}
109150
0 commit comments