Skip to content

Commit befcbba

Browse files
committed
Optimize React State by Moving the State to the sibling
1 parent 91e991c commit befcbba

2 files changed

Lines changed: 101 additions & 46 deletions

File tree

packages/carbon-react-native/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@audira/carbon-react-native",
3-
"version": "1.0.0-beta.9",
3+
"version": "1.0.0-beta.10",
44
"license": "MIT",
55
"homepage": "https://rakadoank.github.io/carbon-react-native",
66
"repository": "https://github.com/RakaDoank/carbon-react-native",

packages/carbon-react-native/src/providers/dialog/DialogProvider.tsx

Lines changed: 100 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {
22
forwardRef,
33
useCallback,
4+
useEffect,
45
useImperativeHandle,
56
useRef,
67
useState,
@@ -29,6 +30,7 @@ import type {
2930

3031
import {
3132
Controller,
33+
type ControllerProps,
3234
type ControllerRef,
3335
} from "./_controller"
3436

@@ -45,50 +47,22 @@ export const DialogProvider = forwardRef<DialogProviderRef, DialogProviderProps>
4547
) {
4648

4749
const
48-
controllerRef =
49-
useRef<ControllerRef>(null),
50-
51-
dialogDataQueue =
52-
useRef<DialogData>(null),
53-
54-
[mountController, setMountController] =
55-
useState(false),
56-
57-
setControllerRef: React.RefCallback<ControllerRef> =
58-
useCallback(ref => {
59-
controllerRef.current = ref
60-
61-
if(controllerRef.current && dialogDataQueue.current) {
62-
controllerRef.current.show({ ...dialogDataQueue.current })
63-
dialogDataQueue.current = null
64-
}
65-
}, []),
50+
controllerWrapperRef =
51+
useRef<ControllerWrapperRef>(null),
6652

6753
show: DialogContext["show"] =
6854
useCallback(data => {
69-
if(!controllerRef.current) {
70-
dialogDataQueue.current = { ...data }
71-
setMountController(true)
72-
} else {
73-
controllerRef.current?.show(data)
74-
}
55+
controllerWrapperRef.current?.show(data)
7556
}, []),
7657

7758
dismiss: DialogContext["dismiss"] =
7859
useCallback(async () => {
79-
return controllerRef.current?.dismiss()
60+
return controllerWrapperRef.current?.dismiss()
8061
}, []),
8162

8263
dismissAll: DialogContext["dismissAll"] =
8364
useCallback(async () => {
84-
return controllerRef.current?.dismissAll()
85-
}, []),
86-
87-
onEmpty =
88-
useCallback(() => {
89-
if(!dialogDataQueue.current) {
90-
setMountController(false)
91-
}
65+
return controllerWrapperRef.current?.dismissAll()
9266
}, [])
9367

9468
useImperativeHandle(ref, () => {
@@ -113,20 +87,101 @@ export const DialogProvider = forwardRef<DialogProviderRef, DialogProviderProps>
11387
>
11488
{ children }
11589

116-
{ mountController && (
117-
<InDialogContext.Provider value={ true }>
118-
<Controller
119-
ref={ setControllerRef }
120-
animationConfig={ animationConfig as typeof DialogAnimationConfigs.CarbonReact }
121-
modalProps={ modalProps }
122-
overlayProps={ overlayProps }
123-
overlayTouchDismiss={ overlayTouchDismiss }
124-
onEmpty={ onEmpty }
125-
/>
126-
</InDialogContext.Provider>
127-
) }
90+
<ControllerWrapper
91+
ref={ controllerWrapperRef }
92+
animationConfig={ animationConfig as typeof DialogAnimationConfigs.CarbonReact }
93+
modalProps={ modalProps }
94+
overlayProps={ overlayProps }
95+
overlayTouchDismiss={ overlayTouchDismiss }
96+
/>
12897
</DialogContext.Provider>
12998
)
13099

131100
},
132101
)
102+
103+
interface ControllerWrapperProps extends Omit<ControllerProps, "onEmpty"> {
104+
ref?: React.Ref<ControllerWrapperRef>,
105+
}
106+
107+
interface ControllerWrapperRef extends ControllerRef {
108+
}
109+
110+
/**
111+
* This is a simple component to save a bit of memory by not mounting the actual `Controller` when it's not needed
112+
*/
113+
function ControllerWrapper({
114+
ref,
115+
...props
116+
}: ControllerWrapperProps) {
117+
118+
const
119+
[mount, setMount] =
120+
useState(false),
121+
122+
controllerRef =
123+
useRef<ControllerRef>(null),
124+
125+
dialogDataQueue =
126+
useRef<DialogData>(null),
127+
128+
onEmpty =
129+
useCallback(() => {
130+
if(!dialogDataQueue.current && controllerRef.current) {
131+
setMount(false)
132+
}
133+
}, [])
134+
135+
useImperativeHandle(ref, () => {
136+
const errMsg = "Error to get the Controller's ref"
137+
138+
return {
139+
show(data) {
140+
if(controllerRef.current) {
141+
controllerRef.current.show(data)
142+
} else {
143+
dialogDataQueue.current = data
144+
setMount(true)
145+
}
146+
},
147+
dismiss() {
148+
if(controllerRef.current) {
149+
return controllerRef.current.dismiss()
150+
}
151+
console.error(errMsg)
152+
return Promise.resolve()
153+
},
154+
dismissAll() {
155+
if(controllerRef.current) {
156+
return controllerRef.current.dismissAll()
157+
}
158+
console.error(errMsg)
159+
return Promise.resolve()
160+
},
161+
}
162+
}, [])
163+
164+
useEffect(() => {
165+
if(mount && dialogDataQueue.current && controllerRef.current) {
166+
controllerRef.current.show({ ...dialogDataQueue.current })
167+
dialogDataQueue.current = null
168+
}
169+
}, [
170+
mount,
171+
])
172+
173+
if(!mount) {
174+
return null
175+
}
176+
177+
return (
178+
<InDialogContext.Provider value>
179+
<Controller
180+
ref={ controllerRef }
181+
{ ...props }
182+
onEmpty={ onEmpty }
183+
/>
184+
</InDialogContext.Provider>
185+
)
186+
187+
}

0 commit comments

Comments
 (0)