@@ -39,6 +39,7 @@ type RefreshOptions = {
3939```
4040
4141** Behavior** :
42+
4243- When ` fetchBeforeClear: true ` : Fetches data first, then clears old state
4344- When ` fetchBeforeClear: false ` (default): Original behavior (clear first, then fetch)
4445- Prevents showing empty state while fetching new data
@@ -48,6 +49,7 @@ type RefreshOptions = {
4849** File** : ` src/store/subscriptionStore.ts `
4950
5051Added dedicated ` refreshSubscriptions() ` method that:
52+
5153- Sets ` isLoading: true ` before fetching
5254- Fetches fresh data atomically
5355- Updates state only after fetch completes
@@ -59,7 +61,7 @@ refreshSubscriptions: async () => {
5961 try {
6062 // Fetch fresh data first
6163 await new Promise ((resolve ) => setTimeout (resolve , 1000 ));
62-
64+
6365 // Update state atomically after fetch completes
6466 set ({ isLoading: false });
6567 get ().calculateStats ();
@@ -73,14 +75,15 @@ refreshSubscriptions: async () => {
7375 isLoading: false ,
7476 });
7577 }
76- }
78+ };
7779```
7880
7981### 3. Updated HomeScreen Integration
8082
8183** File** : ` src/screens/HomeScreen.tsx `
8284
8385Changes:
86+
8487- Import ` refreshSubscriptions ` from store
8588- Import ` isLoading ` state
8689- Use ` refreshSubscriptions ` as fetcher (no ` clearBefore ` needed)
@@ -110,20 +113,24 @@ const onRefresh = async () => {
110113## Acceptance Criteria Met
111114
112115✅ ** AC1: Pull-to-refresh always works**
116+
113117- Concurrent refreshes prevented via ` inFlightRef `
114118- Error handling ensures loading state is cleared
115119
116120✅ ** AC2: No stale data shown**
121+
117122- ` refreshSubscriptions ` fetches before updating state
118123- No intermediate empty state displayed
119124- Cache invalidation handled atomically
120125
121126✅ ** AC3: Loading state correct**
127+
122128- ` isLoading ` set before fetch, cleared after
123129- RefreshControl reflects both ` refreshing ` and ` isLoading `
124130- Proper state transitions: false → true → false
125131
126132✅ ** AC4: No infinite refresh loops**
133+
127134- ` inFlightRef ` prevents concurrent refreshes
128135- Rapid successive refreshes are serialized
129136- Error handling prevents stuck loading state
@@ -133,6 +140,7 @@ const onRefresh = async () => {
133140### Race Condition Prevention
134141
135142** Before** :
143+
136144```
137145T=0ms: clearBefore() → subscriptions: []
138146T=0ms: fetcher() starts
@@ -141,6 +149,7 @@ T=1s: fetchSubscriptions completes → data populates
141149```
142150
143151** After** :
152+
144153```
145154T=0ms: fetcher() starts
146155T=0-1s: UI shows previous data (no flash)
@@ -165,6 +174,7 @@ try {
165174### State Consistency
166175
167176All state updates happen atomically within a single ` set() ` call:
177+
168178- ` isLoading ` flag
169179- ` error ` state
170180- Subscription data (if changed)
@@ -176,6 +186,7 @@ All state updates happen atomically within a single `set()` call:
176186** Test File** : ` src/screens/__tests__/HomeScreen.race-condition.test.ts `
177187
178188Test coverage includes:
189+
179190- AC1: Pull-to-refresh always works
180191- AC2: No stale data shown
181192- AC3: Loading state correct
@@ -184,6 +195,7 @@ Test coverage includes:
184195- State consistency verification
185196
186197Run tests:
198+
187199``` bash
188200npm test -- HomeScreen.race-condition.test.ts
189201```
@@ -195,6 +207,7 @@ npm test -- HomeScreen.race-condition.test.ts
195207If you have custom refresh implementations, update them:
196208
197209** Before** :
210+
198211``` typescript
199212const onRefresh = async () => {
200213 await refresh ({
@@ -205,6 +218,7 @@ const onRefresh = async () => {
205218```
206219
207220** After** :
221+
208222``` typescript
209223const onRefresh = async () => {
210224 await refresh ({
0 commit comments