The React Native Stack I Use in 2026 (And Why)

The React Native Stack I Use in 2026 (And Why)
Feb 19, 202610 views

I'm a software engineer who cares deeply about the product I build, not just the code behind it.

I've spent the last 7 years working with React Native in production environments, building real apps for real users under real constraints. During that time, I've tried a good amount of tools and libraries: Redux with layers of reducers and action types, Context API trees so deep they turned into architecture diagrams, inline styles, styled-components, utility-first approaches, and more dev tools than I can count.

For most of my career, I worked in bare React Native projects, some inside monorepos and long before Expo became my default. I've written custom native modules in Swift and Kotlin, manually bridged third-party SDKs, configured iOS and Android builds from scratch, and debugged my fair share of Xcode and Gradle issues.

I've shipped apps by building directly in Xcode, running Android release commands from the terminal, managing Android Studio configurations, setting up Fastlane and Bitrise pipelines, and pushing OTA updates through CodePush back when App Center was still around.

That experience shaped how I think about architecture, performance, release processes, and trade-offs in mobile development.

State Management

Over time, I've learned that good state management is less about the library you choose and more about being intentional with where state lives.

Local State

For UI-specific concerns, I use React's built-in primitives:

  • useState
  • useRef
  • useMemo or useCallback when necessary

If state only affects a single screen or component, things like form inputs, modal visibility, selected tabs, or small interaction flags; it stays local.

Global State

When state needs to be shared across screens, survive navigation, or represent application-level concerns, I use Zustand.

I've used Redux. I've built large Context-based architectures. They work, but over time I wanted something simpler, with less ceremony and less boilerplate.

Zustand hits the sweet spot.

  • Minimal API
  • No reducers
  • No action types
  • No dispatch pattern
  • Just plain functions updating state

It feels like React, not a framework layered on top of it.

I'm deliberate about what goes into global state. For me, it's typically things like:

  • Auth state (user, session, onboarding status)
  • Feature flags
  • App-level preferences
  • Lightweight cross-screen UI state

The goal is to share what genuinely needs to be shared and do it cleanly.

Data Fetching

For server state, I use TanStack Query.

In the past, I've used Apollo Client for GraphQL and both fetch and Axios for REST APIs. They all work, but the real complexity was never the request itself. It was everything around it: caching, refetching, invalidation, loading states, and keeping data fresh across screens.

TanStack Query handles that layer cleanly.

  • Automatic caching
  • Background refetching
  • Smart invalidation
  • Built-in loading and error states

It treats server state as what it is: asynchronous and owned by the backend, not something that belongs in your global store.

That separation simplified my architecture.

Zustand manages client state.

TanStack Query manages server state.

Clear boundaries. Less duplication. Fewer bugs.

Local Storage & Persistence

For a long time, I used AsyncStorage. It works, it's familiar, and it's usually fine early on. But as apps grow, I started to feel the performance cost, especially around startup time and frequent reads/writes.

These days, I use MMKV.

MMKV is fast and native-backed, which makes a noticeable difference when persistence is part of your critical path (app launch, session restore, rehydrating state).

What I persist is intentional and high-signal:

  • Auth/session details
  • Onboarding completion
  • App preferences (theme, flags, simple settings)
  • A few lightweight values that improve startup UX

MMKV + Zustand

This pairs really nicely with Zustand.

Zustand stays as the source of truth for global client state, and MMKV handles persistence so state can be rehydrated quickly on launch without a bunch of custom hydration work.

Navigation

For years, I used React Navigation as it was the standard choice for stacks, tabs, and complex navigator setups. It's powerful and still widely used.

After moving more seriously into Expo, I switched to Expo Router.

File-based routing made app structure clearer and reduced manual configuration. Routes live alongside features, and deep linking feels more natural.

Expo Router builds on React Navigation, it just simplifies how it's organised.

Less setup, cleaner structure and easier to scale.

Styling

I started with the StyleSheet API, like most React Native developers, often mixing it with inline styles for dynamic values.

Later, I moved to styled-components. It made dynamic styling expressive and clean, and it helped keep UI logic colocated with component structure.

Styled-components hasn't been formally deprecated, but its primary maintainer has stepped back and development has slowed. In practice, many teams now treat it as effectively in maintenance mode and that influenced how I think about abstractions in styling.

These days, I've returned to the StyleSheet API.

  • It's predictable
  • It's performant
  • It keeps styling close to React Native's core primitives

I've also explored NativeWind, a Tailwind-style utility approach that's great for fast UI development. But for most of the apps I build now, I prefer keeping things simple with StyleSheet.

Animations

For animations, I use Reanimated and Lottie.

Reanimated handles interaction-driven animations, gestures, transitions, animated styles, and micro-interactions. It's powerful and performant when used correctly.

For more complex or designer-led animations, I use Lottie. It's especially useful when working closely with a product designer and importing polished motion directly into the app.

I also like using Lottie for splash screen animations as it adds personality to the app from the very first frame.

I'll be writing a deeper post soon on how I approach animations in Expo apps.

Build & Publish

At work, I use EAS since we have a Pro account. It simplifies builds and fits nicely into a modern workflow.

For personal projects, I also use EAS especially when I don't feel like manually building through Xcode or Android Studio.

I haven't explored OTA updates deeply with EAS yet, but I've worked with OTA before using App Center. I've also set up CI/CD pipelines with Bitrise, Codemagic, and Fastlane in the past.

The tooling changes. The fundamentals stay the same.

Dev Tools

The basics still matter.

  • React Native DevTools
  • Console logs (underrated, forever useful)
  • React Profiler for performance monitoring

I've also used Reactotron, which is great for inspecting state and monitoring API calls during development.

Good tooling doesn't replace good architecture but it makes debugging far less painful.

Testing

My foundation has always been:

  • Jest
  • React Native Testing Library

Recently, I've added Storybook for isolated UI development. It helps surface visual issues earlier and keeps components focused.

I haven't had as much opportunity to implement full end-to-end automation in production environments, I've often been my own QA. But if I were setting up E2E today, Maestro would likely be my choice.

Analytics

Right now, my tool of choice is PostHog.

I've used Google Analytics with Firebase and tracked events through AppsFlyer in the past. They work, but PostHog feels more product-focused.

It's simple, powerful, and gives clearer visibility into how users actually move through the app.

AI

I keep this simple for now.

I use Claude and Cursor as development multipliers, for refactoring, test generation, debugging explanations, and documentation.

I'll be writing a deeper post on how I integrate AI into my workflow soon.

Used well, AI doesn't replace thinking. It accelerates it.

Summary

Today, my stack looks like this:

  • Expo / React Native
  • TypeScript
  • Zustand (global client state)
  • TanStack Query (server state)
  • MMKV (persistence)
  • Expo Router (navigation)
  • StyleSheet API (styling)
  • Reanimated & Lottie (animations)
  • EAS (build & distribution)
  • RN DevTools, Profiler, Reactotron (debugging)
  • Jest, RN Testing Library, Storybook (testing)
  • PostHog (analytics)
  • Claude & Cursor (AI)

Simple. Intentional. Product-focused.

The React Native Stack I Use in 2026 (And Why)