@umituz/react-native-design-system 4.25.48 → 4.25.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-design-system",
|
|
3
|
-
"version": "4.25.
|
|
3
|
+
"version": "4.25.49",
|
|
4
4
|
"description": "Universal design system for React Native apps - Consolidated package with atoms, molecules, organisms, theme, typography, responsive, safe area, exception, infinite scroll, UUID, image, timezone, offline, onboarding, and loading utilities",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Artificial delays cause poor UX - the splash should transition as soon as app is ready.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { useState, useEffect } from 'react';
|
|
9
|
+
import { useState, useEffect, useRef } from 'react';
|
|
10
10
|
import { DeviceEventEmitter } from 'react-native';
|
|
11
11
|
|
|
12
12
|
export interface UseSplashFlowOptions {
|
|
@@ -28,11 +28,13 @@ export interface UseSplashFlowResult {
|
|
|
28
28
|
export const useSplashFlow = (options: UseSplashFlowOptions = {}): UseSplashFlowResult => {
|
|
29
29
|
const { isAppReady, duration } = options;
|
|
30
30
|
const [isInitialized, setIsInitialized] = useState(false);
|
|
31
|
+
const isInitializedRef = useRef(false);
|
|
31
32
|
|
|
32
33
|
useEffect(() => {
|
|
33
34
|
// Primary: Use external app ready signal (preferred)
|
|
34
35
|
if (isAppReady !== undefined) {
|
|
35
|
-
if (isAppReady && !
|
|
36
|
+
if (isAppReady && !isInitializedRef.current) {
|
|
37
|
+
isInitializedRef.current = true;
|
|
36
38
|
setIsInitialized(true);
|
|
37
39
|
DeviceEventEmitter.emit('splash-ready');
|
|
38
40
|
}
|
|
@@ -42,15 +44,18 @@ export const useSplashFlow = (options: UseSplashFlowOptions = {}): UseSplashFlow
|
|
|
42
44
|
// Timer-based fallback when isAppReady is not provided
|
|
43
45
|
if (duration !== undefined) {
|
|
44
46
|
const timer = setTimeout(() => {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
+
if (!isInitializedRef.current) {
|
|
48
|
+
isInitializedRef.current = true;
|
|
49
|
+
setIsInitialized(true);
|
|
50
|
+
DeviceEventEmitter.emit('splash-ready');
|
|
51
|
+
}
|
|
47
52
|
}, duration);
|
|
48
53
|
|
|
49
54
|
return () => clearTimeout(timer);
|
|
50
55
|
}
|
|
51
56
|
|
|
52
57
|
return undefined;
|
|
53
|
-
}, [isAppReady, duration
|
|
58
|
+
}, [isAppReady, duration]);
|
|
54
59
|
|
|
55
60
|
return { isInitialized };
|
|
56
61
|
};
|
|
@@ -72,10 +72,12 @@ export function useAsyncOperation<T, E = Error>(
|
|
|
72
72
|
const lastArgsRef = useRef<any[]>([]);
|
|
73
73
|
const retryCountRef = useRef(0);
|
|
74
74
|
|
|
75
|
-
// Stable callback refs
|
|
75
|
+
// Stable callback refs — prevents inline functions from causing execute to be recreated
|
|
76
76
|
const onSuccessRef = useRef(onSuccess);
|
|
77
77
|
const onErrorRef = useRef(onError);
|
|
78
78
|
const onFinallyRef = useRef(onFinally);
|
|
79
|
+
const operationRef = useRef(operation);
|
|
80
|
+
const errorHandlerRef = useRef(errorHandler);
|
|
79
81
|
|
|
80
82
|
useEffect(() => {
|
|
81
83
|
onSuccessRef.current = onSuccess;
|
|
@@ -83,6 +85,10 @@ export function useAsyncOperation<T, E = Error>(
|
|
|
83
85
|
onFinallyRef.current = onFinally;
|
|
84
86
|
}, [onSuccess, onError, onFinally]);
|
|
85
87
|
|
|
88
|
+
// Keep operation and errorHandler in refs so execute doesn't need them as deps
|
|
89
|
+
operationRef.current = operation;
|
|
90
|
+
errorHandlerRef.current = errorHandler;
|
|
91
|
+
|
|
86
92
|
// Cleanup on unmount
|
|
87
93
|
useEffect(() => {
|
|
88
94
|
return () => {
|
|
@@ -104,7 +110,7 @@ export function useAsyncOperation<T, E = Error>(
|
|
|
104
110
|
}
|
|
105
111
|
|
|
106
112
|
try {
|
|
107
|
-
const result = await
|
|
113
|
+
const result = await operationRef.current(...args);
|
|
108
114
|
|
|
109
115
|
if (isMountedRef.current) {
|
|
110
116
|
setData(result);
|
|
@@ -114,7 +120,7 @@ export function useAsyncOperation<T, E = Error>(
|
|
|
114
120
|
|
|
115
121
|
return result;
|
|
116
122
|
} catch (err) {
|
|
117
|
-
const handledError =
|
|
123
|
+
const handledError = errorHandlerRef.current(err);
|
|
118
124
|
|
|
119
125
|
if (isMountedRef.current) {
|
|
120
126
|
setErrorState(handledError);
|
|
@@ -129,7 +135,7 @@ export function useAsyncOperation<T, E = Error>(
|
|
|
129
135
|
}
|
|
130
136
|
}
|
|
131
137
|
},
|
|
132
|
-
[
|
|
138
|
+
[skip]
|
|
133
139
|
);
|
|
134
140
|
|
|
135
141
|
const retry = useCallback(async (): Promise<T | null> => {
|