React Native Flow

← Retour au blog

April 1, 2026·10 min read

In-app purchases: the mental model mobile devs need

IAP looks like “call API, unlock feature.” It’s really: products, offers, transactions, renewals, refunds, and server validation. Client libraries help, but the source of truth for entitlements is usually your backend. Plan for support and finance questions on day one—they arrive before edge cases do.

Sandbox pain is normal

Test accounts, slow renewals, and weird caching are part of the job. Build logging around purchase callbacks.

Never trust the client alone for premium content gating long term.

Restore purchases

Apple requires it; users expect it. Make it obvious and fast, not buried in settings submenus.

Handle “already owned” gracefully.

Edge cases

Family sharing, upgrades, intro offers, and regional pricing all hit your SKU design. Read platform docs when finance changes prices.

Support needs tooling to look up a user’s subscription state.

What to sync with product and legal

Refund windows, grace periods, and “what happens when payment fails” should match what your paywall copy promises. Engineering exposes state; product owns the story users hear.

Log purchase lifecycle events with enough detail to debug without storing full receipts in analytics—use your backend as the system of record.

Store economics and engineering reality

In-app purchases sit at the intersection of finance, legal, and platform policy. Apple and Google set timelines for payouts, refunds, and disputes—your app must surface entitlements accurately despite asynchronous updates. Never assume purchase callbacks arrive in order; network reordering happens. Subscriptions renew on server clocks, not device clocks—handle grace periods and billing retries as first-class states. Family sharing, introductory pricing, and regional taxes affect what users see—coordinate copy with finance. Fraud exists: receipt replay, stolen accounts—server validation is mandatory for anything beyond cosmetic unlocks. Support teams need tools to look up subscription status with minimal PII exposure—build admin panels with audit logs. When currency changes or price experiments run, ensure client displays match store receipts users see—mismatches generate chargebacks and bad reviews.

Sandbox testing and where it lies to you

Sandbox renewals accelerate unnaturally; test durations differ from production. Create dedicated tester accounts per platform and document their quirks—password resets, region locks, and family organizer settings. Keep test accounts out of analytics dashboards—tag events clearly. Flaky purchases often trace to store outages or account configuration—have status page monitors. For Expo workflows, know when you need custom dev clients versus store builds—native IAP requires real binaries eventually. After native upgrades, rerun IAP smoke tests—billing libraries break across store SDK changes. Document known issues per OS version—StoreKit and Play Billing release notes are essential reading before releases.

Restore purchases, edge cases, and user trust

Restore flows must be obvious—Apple requires discoverable restore; users expect it after reinstalls or device changes. Handle ‘already owned’ and ‘nothing to restore’ gracefully with human copy. Multi-account users switch Apple IDs—guide them without blaming. When server validation lags, show pending states instead of hard failures. For upgrades/downgrades between tiers, map proration rules clearly—confusion drives support tickets. If subscriptions bundle web access, ensure mobile purchase flows do not violate platform rules about steering users to external payment—legal review required. Enterprise volume purchases may use different mechanics—segment analytics accordingly.

Observability and operational readiness

Log purchase lifecycle events with structured codes—avoid free-text reasons. Monitor conversion funnels from product page view through completion; drop-offs highlight UX issues. Alert on validation error spikes—they may indicate server bugs or store incidents. Maintain runbooks for common failures: receipt expired, invalid product id, user canceled. Coordinate releases with finance on tax and invoice changes. After major IAP library upgrades, watch review times—billing changes sometimes trigger extra scrutiny. Treat money-moving code with the same on-call seriousness as payments web—mobile is not ‘lighter’ responsibility.

Shipping and reliability habits (1)

Environment variables should be classified: public-by-design, sensitive-with-mitigations, or never-on-device. `EXPO_PUBLIC_` values are extractable—treat them that way. Align env handling across EAS profiles and local dev; fail fast when keys are missing instead of shipping undefined behavior.

Project structure should make ownership obvious: routes as backbone, feature folders for product areas, thin screens, and shared infrastructure that is deliberately named. Refactor in vertical slices with device-tested releases—big-bang rewrites without tests are how teams lose weeks.

Platform differences worth rehearsing (2)

Monorepos amplify both leverage and failure modes: duplicate React versions cause mysterious hook errors, and Metro misconfiguration blocks local packages from resolving. Invest in workspace discipline—single React version, documented `watchFolders`, and lint rules preventing packages from importing app navigators accidentally. CI must mirror local installs; ‘works on my laptop’ with different package managers is a time bomb.

Native modules are product decisions disguised as engineering tasks. You inherit Xcode and Gradle upgrades, store review scrutiny, and security obligations. Prefer maintained Expo modules and config plugins before writing JNI or Swift glue from scratch. When you must go native, budget pairing time with platform specialists and write runbooks for on-call—crashes in native code bypass many JS safeguards.

Security, privacy, and data handling (3)

E2E tests should protect revenue paths, not every permutation. Stable selectors (`testID`) beat text that marketing rewrites weekly. Flake management is a feature: quarantine, fix root causes, and keep smoke suites green on CI devices. Five reliable tests beat fifty flaky ones that everyone ignores.

OTA updates are powerful and risky: runtime compatibility, rollback plans, and user-visible behavior changes need governance. Channels should map to release maturity—staging versus production—with access controls on publish credentials. Large assets over cellular need care; silent failures erode trust more than a frank ‘update failed, retry’ message.

Performance and measurement discipline (4)

Privacy nutrition labels and Play Data Safety forms should reflect actual SDK behavior—inventory dependencies each release and remove dead code. Drift between claims and telemetry is legal and store risk, not just embarrassment. Involve legal early when adding analytics or ads.

Expo SDK upgrades are integration projects: `expo doctor`, aligned community packages, regenerated native projects, and device smoke tests for camera, push, and IAP. Freeze unrelated native refactors during the upgrade window and keep rollback paths hot. Document surprises for the next upgrade while memory is fresh.

Team process and long-term maintenance (5)

ScrollView versus FlatList is a data-volume question. Small static content belongs in ScrollView; long feeds belong in virtualized lists. Nested scrollables need explicit height contracts—redesign beats fighting physics. Document intentional choices so future refactors do not ‘optimize’ blindly.

Metro cache issues masquerade as logic bugs. Establish a documented reset ladder: dev server restart, cache flags, Watchman, derived data, then dependency reinstalls. Compare platforms when only one breaks—native steps diverge. Keep CI caches deterministic with lockfiles and pinned toolchains.

Shipping and reliability habits (6)

Accessibility is compatibility. Labels, focus order, and dynamic type are not polish—they determine whether users can complete tasks at all. Test with VoiceOver and TalkBack on hardware; simulators miss focus bugs. When designs prioritize minimalism, negotiate text alternatives for icon-only controls. Accessibility regressions often follow navigation redesigns—add checklist items to those PRs specifically.

Internationalization is a product feature, not a string swap. Plural rules, RTL layout, and locale-aware formatting change behavior—not just copy length. Pseudolocale helps find clipping early, but real Arabic and German QA catches nuance. Avoid concatenating translated fragments; context matters. Document glossary terms so translators do not invent inconsistent product names.

Platform differences worth rehearsing (7)

Storage is not a database. AsyncStorage and MMKV excel at key-value preferences; SQLite or remote APIs belong elsewhere for relational data. Migrations should be incremental, logged, and non-blocking for UI. Secure tokens need secure storage when your model demands it—speed is not a substitute for correctness on auth material.

WebViews are untrusted browsers inside your app. Validate `postMessage` payloads, lock navigation to expected hosts, and prefer system-browser auth flows when OAuth security demands it. Third-party JavaScript can change without your deploy—treat XSS in web as bridge compromise risk. Clear storage on logout and rate-limit message handlers.

Security, privacy, and data handling (8)

JWT and session refresh flows need single-flight refresh, clear logout semantics, and secure storage for refresh tokens when appropriate. Parallel 401s should not stampede refresh endpoints. Clock skew and biometrics policies belong in explicit product decisions, not accidental implementation details.

In-app purchases require server validation, restore flows, and support tooling that respects privacy. Sandbox quirks are normal—budget QA time. Subscriptions interact with family sharing, regional pricing, and refunds; engineering must stay aligned with finance and legal narratives users see in receipts.

Performance and measurement discipline (9)

Background execution policies change with OS updates—revalidate after major iOS and Android releases. Misused background modes invite rejection. Persist user work frequently; the OS can kill you anytime after backgrounding. Uploads and timers should tolerate pause and resume without corrupting state.

Design tokens and semantic colors make dark mode and rebrands feasible. Mixing three styling systems doubles migration cost—pick a primary approach and draw boundaries. Runtime CSS-in-JS can cost frame time on hot screens—profile before adopting wholesale.

Team process and long-term maintenance (10)

Performance work should start with measurement, not instinct. Watch JS thread versus UI thread separately; they bottleneck differently. Lists, images, and animations dominate most regressions—optimize those before micro-optimizing pure functions. Hermes, JSC, and bridge internals evolve; re-profile after every major upgrade instead of trusting last year’s numbers. Battery and thermal throttling on mid devices reveal issues flagship phones hide.

Security and privacy expectations move faster than roadmaps. Treat analytics, crash, and attribution SDKs as part of your threat model: initialize them deliberately, document data flows, and verify ‘off’ truly stops network calls. Client-side secrets are public secrets—anything shipped in an APK or IPA should be assumed extractable. Pair mobile changes with backend policies so authorization remains consistent across platforms.

Shipping and reliability habits (11)

Internationalization is a product feature, not a string swap. Plural rules, RTL layout, and locale-aware formatting change behavior—not just copy length. Pseudolocale helps find clipping early, but real Arabic and German QA catches nuance. Avoid concatenating translated fragments; context matters. Document glossary terms so translators do not invent inconsistent product names.

Monorepos amplify both leverage and failure modes: duplicate React versions cause mysterious hook errors, and Metro misconfiguration blocks local packages from resolving. Invest in workspace discipline—single React version, documented `watchFolders`, and lint rules preventing packages from importing app navigators accidentally. CI must mirror local installs; ‘works on my laptop’ with different package managers is a time bomb.

Platform differences worth rehearsing (12)

WebViews are untrusted browsers inside your app. Validate `postMessage` payloads, lock navigation to expected hosts, and prefer system-browser auth flows when OAuth security demands it. Third-party JavaScript can change without your deploy—treat XSS in web as bridge compromise risk. Clear storage on logout and rate-limit message handlers.

E2E tests should protect revenue paths, not every permutation. Stable selectors (`testID`) beat text that marketing rewrites weekly. Flake management is a feature: quarantine, fix root causes, and keep smoke suites green on CI devices. Five reliable tests beat fifty flaky ones that everyone ignores.

Security, privacy, and data handling (13)

In-app purchases require server validation, restore flows, and support tooling that respects privacy. Sandbox quirks are normal—budget QA time. Subscriptions interact with family sharing, regional pricing, and refunds; engineering must stay aligned with finance and legal narratives users see in receipts.

Privacy nutrition labels and Play Data Safety forms should reflect actual SDK behavior—inventory dependencies each release and remove dead code. Drift between claims and telemetry is legal and store risk, not just embarrassment. Involve legal early when adding analytics or ads.

Performance and measurement discipline (14)

Design tokens and semantic colors make dark mode and rebrands feasible. Mixing three styling systems doubles migration cost—pick a primary approach and draw boundaries. Runtime CSS-in-JS can cost frame time on hot screens—profile before adopting wholesale.

ScrollView versus FlatList is a data-volume question. Small static content belongs in ScrollView; long feeds belong in virtualized lists. Nested scrollables need explicit height contracts—redesign beats fighting physics. Document intentional choices so future refactors do not ‘optimize’ blindly.

Team process and long-term maintenance (15)

Security and privacy expectations move faster than roadmaps. Treat analytics, crash, and attribution SDKs as part of your threat model: initialize them deliberately, document data flows, and verify ‘off’ truly stops network calls. Client-side secrets are public secrets—anything shipped in an APK or IPA should be assumed extractable. Pair mobile changes with backend policies so authorization remains consistent across platforms.

Accessibility is compatibility. Labels, focus order, and dynamic type are not polish—they determine whether users can complete tasks at all. Test with VoiceOver and TalkBack on hardware; simulators miss focus bugs. When designs prioritize minimalism, negotiate text alternatives for icon-only controls. Accessibility regressions often follow navigation redesigns—add checklist items to those PRs specifically.

Sponsorisé

Promo rapide