@umituz/react-native-subscription 2.26.9 → 2.26.10

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-subscription",
3
- "version": "2.26.9",
3
+ "version": "2.26.10",
4
4
  "description": "Complete subscription management with RevenueCat, paywall UI, and credits system for React Native apps",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -166,9 +166,10 @@ export class CreditsRepository extends BaseRepository {
166
166
  isPremium: false,
167
167
  status: "free" as const,
168
168
 
169
- // Free credits
169
+ // Free credits - store initial amount for tracking
170
170
  credits: freeCredits,
171
171
  creditLimit: freeCredits,
172
+ initialFreeCredits: freeCredits,
172
173
  isFreeCredits: true,
173
174
 
174
175
  // Dates
@@ -7,7 +7,7 @@
7
7
  */
8
8
 
9
9
  import { useQuery } from "@umituz/react-native-design-system";
10
- import { useCallback, useMemo, useRef, useEffect } from "react";
10
+ import { useCallback, useMemo, useEffect } from "react";
11
11
  import type { UserCredits } from "../../domain/entities/Credits";
12
12
  import {
13
13
  getCreditsRepository,
@@ -27,6 +27,12 @@ const DEFAULT_STALE_TIME = 30 * 1000;
27
27
  /** Default gc time: 5 minutes */
28
28
  const DEFAULT_GC_TIME = 5 * 60 * 1000;
29
29
 
30
+ /**
31
+ * Global tracker for free credits initialization attempts.
32
+ * Shared across all useCredits hook instances to prevent multiple inits.
33
+ */
34
+ const freeCreditsInitAttempted = new Set<string>();
35
+
30
36
  export interface CreditsCacheConfig {
31
37
  /** Time in ms before data is considered stale. Default: 30 seconds */
32
38
  staleTime?: number;
@@ -66,9 +72,6 @@ export const useCredits = ({
66
72
 
67
73
  const queryEnabled = enabled && !!userId && isConfigured;
68
74
 
69
- // Track if free credits initialization has been attempted
70
- const freeCreditsInitAttemptedRef = useRef<string | null>(null);
71
-
72
75
  const { data, isLoading, error, refetch, isFetched } = useQuery({
73
76
  queryKey: creditsQueryKeys.user(userId ?? ""),
74
77
  queryFn: async () => {
@@ -113,16 +116,17 @@ export const useCredits = ({
113
116
  // 3. No credits data exists
114
117
  // 4. Free credits configured
115
118
  // 5. Auto-init enabled
116
- // 6. Haven't already attempted for this user
119
+ // 6. Haven't already attempted for this user (global tracking)
117
120
  if (
118
121
  isFetched &&
119
122
  userId &&
120
123
  isConfigured &&
121
124
  !credits &&
122
125
  autoInit &&
123
- freeCreditsInitAttemptedRef.current !== userId
126
+ !freeCreditsInitAttempted.has(userId)
124
127
  ) {
125
- freeCreditsInitAttemptedRef.current = userId;
128
+ // Mark as attempted IMMEDIATELY to prevent other hook instances
129
+ freeCreditsInitAttempted.add(userId);
126
130
 
127
131
  if (typeof __DEV__ !== "undefined" && __DEV__) {
128
132
  console.log("[useCredits] Auto-initializing free credits for new user:", userId.slice(0, 8));
@@ -134,7 +138,6 @@ export const useCredits = ({
134
138
  if (typeof __DEV__ !== "undefined" && __DEV__) {
135
139
  console.log("[useCredits] Free credits initialized:", result.data?.credits);
136
140
  }
137
- // Refetch to get the new credits
138
141
  refetch();
139
142
  } else {
140
143
  if (typeof __DEV__ !== "undefined" && __DEV__) {