@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.48",
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 && !isInitialized) {
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
- setIsInitialized(true);
46
- DeviceEventEmitter.emit('splash-ready');
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, isInitialized]);
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 operation(...args);
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 = errorHandler(err);
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
- [operation, skip, errorHandler]
138
+ [skip]
133
139
  );
134
140
 
135
141
  const retry = useCallback(async (): Promise<T | null> => {