Przejdź do treści
Biblioteka skilli
Programowanie · Przegląd i audyt

rn-async-patterns

/rn-async-patterns

Sprawdza poprawność asynchroniczności w React Native z Zustand, szukając wyścigów, brakujących await i wiszących promise.

Repozytorium
SkillCamo ↗
Licencja
Apache-2.0
Ostatnia zmiana repozytorium
04.11.2026

Ocena i bezpieczeństwo

100/ 100Klasa: dobry
Format25 / 25
Frontmatter z nazwą i opisem, poprawna nazwa, opis do 1024 znaków, nazwa zgodna z folderem.
Odkrywalność25 / 25
Opis mówi, kiedy użyć skilla, ma sensowną długość i jest w 3. osobie.
Treść35 / 35
Co najmniej 150 słów i do 500 linii, nagłówki, listy kroków, przykłady albo kod.
Higiena15 / 15
Bez zaślepek typu TODO, bez ścieżek Windows, z licencją.
Ryzykobrak sygnałów w skanie
Pliki w paczce
1
Skrypty
0
Komentarze HTML
0
Adresy URL w SKILL.md
0
Przestarzałość

Brak sygnałów. Repozytorium zmienione 04.11.2026, bez odwołań do wycofanych modeli i API.

Licencja

Apache-2.0, otwarta: można używać i zmieniać, z zachowaniem licencji i informacji o zmianach.

Co robi i kiedy

Sprawdza poprawność asynchroniczności w React Native z Zustand, szukając wyścigów, brakujących await i wiszących promise.

Oryginalny opis (EN)

Async/await correctness in React Native with Zustand. Use when debugging race conditions, missing awaits, floating promises, or async timing issues in Expo/React Native apps.

Jak działa

  1. Problem Statement
  2. Pattern: Floating Promise Detection
  3. Pattern: Post-Condition Validation
  4. Pattern: Async Function Identification
  5. Pattern: Sequential vs Parallel Async
  6. Pattern: Async in useEffect
  7. ESLint Configuration
  8. Code Review Checklist
  9. Quick Debugging
Sekcje z nagłówków SKILL.md, w oryginale · 252 linii, 889 słów
Podgląd SKILL.md
---
name: rn-async-patterns
description: Async/await correctness in React Native with Zustand. Use when debugging race conditions, missing awaits, floating promises, or async timing issues in Expo/React Native apps.
---

# React Native Async Patterns

## Problem Statement

Async bugs in React Native are insidious because they often work in development but fail under load or on slower devices. The most common issues: missing `await` on async functions, race conditions between state updates, and assuming operations complete in order.

---

## Pattern: Floating Promise Detection

**Problem:** Calling an async function without `await` causes it to run in the background. If subsequent code depends on its completion, you get a race condition.

**Example (from retake bug):**

```typescript
// Before (buggy) - enableSkillAreaRetake is async but not awaited
enableSkillAreaRetake(skillArea);         // Fire and forget ❌
await clearSkillAreaAnswers(skillArea);   // Runs before enable completes

// After (fixed)
await enableSkillAreaRetake(skillArea);   // Wait for state update ✅
await clearSkillAreaAnswers(skillArea);   // Now runs in correct order
```

**Why it's subtle:** Both functions might have `async` in their signature, but only one was awaited. The code "looks right" at a glance.

**Detection:**

```bash
# Find potential floating promises - async calls without await
grep -rn "^\s*[a-zA-Z]*\s*(" --include="*.ts" --include="*.tsx" | \
  grep -v "await\|return\|const\|let\|if\|else\|=>"
```

**Prevention:**

1. ESLint rule `@typescript-eslint/no-floating-promises` - catches this at lint time
2. Code review trigger: Any line calling a function that might be async without `await`, `return`, or assignment

---

## Pattern: Post-Condition Validation

**Problem:** Assuming an async call succeeded without verifying. The call might return early, throw silently, or fail to update state.

**Example (from retake bug):**

```typescript
// Before (buggy) - assumed load worked
await loadCompletedAssessmentAnswers(id);
// Proceeded blindly with retake flow...

// After (defensive)
await loadCompletedAssessmentAnswers(id);
const loaded = useAssessmentStore.getState().completedAssessmentAnswers;
if (Object.keys(loaded).length === 0) {
  throw new Error(
    `Failed to load answers for assessment ${id} - cannot proceed with retake`
  );
}
```

**Principle:** Treat every async call as potentially failed until proven otherwise.

**When to validate:**

- After loading data that subsequent operations depend on
- After state updates that must complete before continuing
- Before irreversible operations (submissions, deletions)

**Pattern template:**

```typescript
await someAsyncOperation();
const result = getRelevantState();
if (!isValid(result)) {
  throw new Error(`[${functionName}] Post-condition failed: ${diagnosticContext}`);
}
```

---

## Pattern: Async Function Identification

**Problem:** Not all async functions look async. Zustand actions, callbacks, and promise-returning functions may not have obvious `async` keywords.

**Hidden async patterns:**

```typescript
// Obvious async
async function fetchData() { ... }

// Less obvious - returns Promise
function fetchData(): Promise<Data> { ... }

// Hidden - Zustand action that's actually async
const useStore = create((set, get) => ({
  // This looks sync but calls async internally
  enableRetake: (area: string) => {
    someAsyncSetup().then(() => {  // ← Hidden async!
      set({ retakeAreas: [...get().retakeAreas, area] });
    });
  },
}));

// Proper async Zustand action
const useStore = create((set, get) => ({
  enableRetake: async (area: string) => {
    await someAsyncSetup();
    set({ retakeAreas: [...get().retakeAreas, area] });
  },
}));
```

**Detection:** Check function signatures and implementations:

```bash
# Find functions returning Promise
grep -rn "): Promise<" --include="*.ts" --include="*.tsx"

# Find .then() chains that might need await
grep -rn "\.then(" --include="*.ts" --include="*.tsx"
```

---

## Pattern: Sequential vs Parallel Async

**Problem:** Running async operations sequentially when they could be parallel (slow), or parallel when they must be sequential (race condition).

```typescript
// Sequential - correct when order matters
await enableSkillAreaRetake(skillArea);
await clearSkillAreaAnswers(skillArea);
await loadRetakeQuestions(skillArea);

// Parallel - correct when operations are independent
const [user, settings, history] = await Promise.all([
  fetchUser(id),
  fetchSettings(id),
  fetchHistory(id),
]);

// WRONG - parallel when order matters
await Promise.all([
  enableSkillAreaRetake(skillArea),   // These have dependencies!
  clearSkillAreaAnswers(skillArea),
]);
```

**Decision framework:**

| Operations share state? | Must run in order? | Pattern |
|------------------------|-------------------|---------|
| No | No | `Promise.all()` |
| Yes | Yes | Sequential `await` |
| Yes | No | Usually sequential to be safe |

---

## Pattern: Async in useEffect

**Problem:** `useEffect` callbacks can't be async directly. Common mistakes with cleanup and race conditions.

```typescript
// WRONG - useEffect can't be async
useEffect(async () => {
  const data = await fetchData();
  setData(data);
}, []);

// CORRECT - async function inside
useEffect(() => {
  async function load() {
    const data = await fetchData();
    setData(data);
  }
  load();
}, []);

// BETTER - with cleanup for race conditions
useEffect(() => {
  let cancelled = false;
  
  async function load() {
    const data = await fetchData();
    if (!cancelled) {
      setData(data);
    }
  }
  load();
  
  return () => {
    cancelled = true;
  };
}, [dependency]);
```

---

## ESLint Configuration

Apply config from `configs/eslint-async.json` to catch these issues at lint time:

```json
{
  "rules": {
    "@typescript-eslint/no-floating-promises": "error",
    "@typescript-eslint/require-await": "warn",
    "@typescript-eslint/await-thenable": "error",
    "@typescript-eslint/no-misused-promises": "error"
  }
}
```

**Required:** `@typescript-eslint/eslint-plugin` and proper TypeScript configuration.

---

## Code Review Checklist

When reviewing async code, check:

- [ ] Every async function call is either `await`ed, `return`ed, or explicitly fire-and-forget with comment
- [ ] Operations that depend on each other are sequenced with `await`
- [ ] Post-conditions validated after critical async operations
- [ ] `useEffect` with async uses the inner function pattern
- [ ] Race conditions considered when component could unmount during async
- [ ] Error handling exists for async failures

---

## Quick Debugging

When async timing issues occur:

```typescript
// Add timestamps to trace execution order
console.log(`[${Date.now()}] Starting enableRetake`);
await enableSkillAreaRetake(skillArea);
console.log(`[${Date.now()}] Finished enableRetake`);
console.log(`[${Date.now()}] Starting clearAnswers`);
await clearSkillAreaAnswers(skillArea);
console.log(`[${Date.now()}] Finished clearAnswers`);
```

Look for:
- Operations finishing out of expected order
- Operations starting before previous ones complete
- Suspiciously fast "completions" (might not have awaited)

Wersje

W bazie nie ma innych skilli o nazwie rn-async-patterns.

Migawka bazy z 13.11.2026 · wersja paczki a63574f240cf (skrót SHA-256 całej paczki)

Pobrania w ostatnich 30 dniach: 0 · ranking

Zgłoś problem z tym skillem: szkodliwa treść, błędny opis albo prośba autora o usunięcie.

Podobne skille

  • 100async-await-patterns
    Pomaga pisać kod JavaScript i TypeScript z operacjami asynchronicznymi, naprawiać błędy promisów i zamieniać callbacki lub łańcuchy promise na async/await.
  • 91typescript-async-patterns
    Pomaga pisać asynchroniczny kod TypeScript z Promises, async/await i iteratorami asynchronicznymi z poprawnym typowaniem.
  • 100gpui-async
    Pokazuje wzorce asynchroniczności i współbieżności w aplikacjach GPUI: zadania w tle, async/await, zarządzanie zadaniami i operacje współbieżne.
  • 100react-native-state-management
    Wdraża lokalny i globalny stan w React Native z Context, Zustand i Redux Toolkit oraz pomaga wybrać rozwiązanie.
  • 100reviewing-concurrency-and-async
    Szuka w kodzie współbieżnym i asynchronicznym wyścigów oraz błędów kolejności, na przykład check-then-act przez await, nieczekające promesy i brak anulowania.
  • 90js-async-patterns
    Pomaga poprawnie składać asynchroniczny JavaScript z promises i async/await, propagować błędy i anulować operacje przez AbortController.

Uwagi i zgłoszenia

Wiadomość trafi do Bartosza Sokolińskiego. Adres e-mail jest potrzebny tylko do odpowiedzi. Szczegóły w polityce prywatności.