React Native Flow

← Retour au blog

March 17, 2026·10 min read

Error boundaries in React Native (the honest version)

Boundaries catch render errors in children—not async errors, not native crashes, not every event handler throw depending on how it propagates. They’re still worth wrapping risky feature islands. Pair them with real crash tooling so you are not pretending JavaScript caught what only the OS saw.

Wrap feature roots

A boundary around a tab or a heavy chart means the rest of the navigator keeps working. Pair with logging so you see the stack in your crash tool.

Reset state on retry if the error was data-dependent.

What won’t save you

Native module exceptions, OOMs, and some bridge errors bypass React entirely. You still need platform crash reporting.

Don’t swallow errors silently in production; users deserve a message and you deserve a breadcrumb.

Dev vs prod UX

In dev, show details. In prod, show human copy plus an error id. Link to support if that’s your workflow.

Test the fallback UI with screen readers.

What to log with the fallback

Include route name, build version, and a correlation id users can quote to support. Avoid logging PII; hash user ids if you must tie sessions together.

Reproduce paths: boundary errors often spike after a bad deploy—tag releases so you can roll back OTA or store builds quickly.

Boundary placement strategy

Wrap navigators or feature roots so one broken leaf does not blank the entire app. Pair boundaries with telemetry that captures component stacks and route context. Avoid boundaries so granular that they mask systemic issues—too many tiny boundaries increase noise. For data-heavy charts or third-party SDK screens, boundaries are especially valuable: you can disable a feature while keeping core flows alive.

What errors boundaries will not catch

Event handlers, async code, and many native crashes bypass React error boundaries. Use try/catch in async flows and global handlers where appropriate. Native crash reporting remains mandatory. Do not promise users that boundaries prevent all crashes—set expectations internally too.

Fallback UI that respects users

Show concise messaging, a recovery action, and a support path. Include build version and error id. For logged-in users, avoid logging out automatically unless necessary—dropping auth worsens perception. Test fallbacks with screen readers and large text. Dark mode styling matters—errors look careless if poorly contrasted.

Logging and PII minimization

Capture stack traces without embedding personal data. Hash identifiers if you need correlation. Sample high-volume errors to control costs. Tag errors with feature flags and experiments to spot rollout-related spikes quickly. Align with privacy policy on what diagnostic data you collect in production.

Development versus production behavior

In dev, show detailed errors to engineers. In prod, hide internals from users but route rich context to your logging pipeline. Guard dev overlays so they never ship accidentally. Use feature flags to canary boundary changes—misconfigured boundaries can hide real issues during testing if too aggressive.

Testing boundaries

Intentionally throw in test builds to verify fallback UI and logging. Snapshot fallback screens for design review. Ensure retry paths reset bad state—otherwise users loop through failures. Automate a smoke test that triggers a controlled error in staging environments.

Operational follow-through

Track error rates post-release; set alerts on spikes. Triage duplicates and route to owners. Close the loop with QA and design when fallbacks confuse users. Boundaries are part of reliability engineering, not just React trivia.

Shipping and reliability habits (1)

Helper modules concentrate glue code—storage, navigation, permissions—so screens stay readable. Split helpers by topic before files become merge-conflict magnets, and document each module’s contract. Good helpers answer ‘where do we save tokens?’ in one glance—not ‘ask Sarah.’

Shipping React Native features is less about any single API and more about the system around it: typed boundaries, predictable navigation, and telemetry that tells you what broke in production. Prefer boring, explicit modules over clever metaprogramming that the next hire cannot grep. When platform vendors change behavior in point releases, your defense is automated smoke tests on real devices and a short internal changelog of native assumptions you rely on.

Platform differences worth rehearsing (2)

Deep links are a cross-team system: marketing URLs, hosted association files, entitlements, router params, and analytics query preservation. Debug with structured logging of raw URLs (scrub secrets) and reproduce cold-start races with auth hydration. Staging and production should be obviously separated—accidentally opening prod from a QA link erodes trust and pollutes data.

Push notifications walk a line between helpful and intrusive. Prime users with context, respect notification channels on Android, and measure opt-outs after campaigns—spikes mean copy or frequency problems. Payload design affects background behavior; test killed and locked-device states. Tokens belong server-side with rotation strategies; never treat the client as authoritative for subscription state.

Security, privacy, and data handling (3)

Keyboard and form UX separate polished apps from ‘works on desktop simulators.’ Platform differences in soft input modes matter; test smallest phones and Android gesture navigation. Primary actions must remain reachable when the keyboard is visible—scroll containers and keyboard controllers exist because this problem is universal.

Type-safe navigation pays off when routes multiply. Keep param lists near navigators, validate external URLs, and avoid serializing non-JSON-safe values through params. Renaming routes is a cross-cutting change—update analytics, push payloads, and E2E selectors in the same release train.

Performance and measurement discipline (4)

Hermes versus JSC is not a lifestyle choice—profile your app. Hermes usually wins on startup; some libraries still assume JSC quirks. Engine toggles are not substitutes for fixing quadratic renders in your own code. Upgrade notes matter: Intl support and debugging tooling evolve.

Reanimated and gesture libraries earn their place when profiling proves UI-thread work and your team can maintain native upgrades. Worklets have constraints—read errors carefully. Respect reduced motion and test Android timing differences—identical JS does not guarantee identical feel.

Team process and long-term maintenance (5)

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.

Shipping and reliability habits (6)

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.

Platform differences worth rehearsing (7)

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.

Security, privacy, and data handling (8)

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.

Performance and measurement discipline (9)

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.

Team process and long-term maintenance (10)

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.

Shipping and reliability habits (11)

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.

Platform differences worth rehearsing (12)

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.

Security, privacy, and data handling (13)

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.

Performance and measurement discipline (14)

Error boundaries catch render failures, not native crashes or async mistakes. Pair them with platform crash reporting and structured client logs. Fallback UI should include build identifiers and humane copy—never raw stack traces for end users. Test fallbacks with screen readers; a broken error screen is still broken UX.

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.

Team process and long-term maintenance (15)

Splash screens and launch gates should reflect honest readiness: fonts, theme, session, critical remote config—not every SDK under the sun. Infinite splash is worse than a slightly longer branded hold. Match native and JS background colors to avoid flashes; respect reduced motion for animations.

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.

Sponsorisé

Promo rapide