Technology·14 min read

React Native for Apple Watch and WearOS: Companion App Guide

React Native does not natively support watchOS or WearOS, but that does not mean you need to build entirely separate native apps. The right bridging strategy gives you shared business logic with native watch UIs.

Nate Laquis

Nate Laquis

Founder & CEO

Why React Native Teams Need a Watch Strategy

If you have a React Native app in production and your product team is asking about Apple Watch or WearOS support, the first thing you need to understand is this: you cannot render React Native views on a watch. There is no React Native runtime for watchOS or WearOS. Full stop. Anyone telling you otherwise is selling something that does not exist.

But that does not mean the situation is bleak. The real architecture for watch companion apps is a hybrid one. Your React Native phone app stays exactly as it is. You add a native watch target (SwiftUI for watchOS, Jetpack Compose for WearOS) that communicates with the phone app through platform-specific bridging APIs. The watch app handles its own tiny UI. The phone app handles the heavy logic. They talk to each other over Watch Connectivity (iOS) or the Data Layer API (Android).

This pattern works well because watches are not phones. The screen is 1.5 to 2 inches. Users interact for 5 to 15 seconds at a time. The processor is roughly equivalent to a phone from 2015. Battery life is measured in hours, not days. You do not need a full application framework on the wrist. You need a thin native UI that shows the right data at the right time and sends commands back to the phone.

Smartphones and smartwatch devices showing companion app interfaces for fitness tracking

The teams I have worked with that succeed at this treat the watch app as a dedicated native module project, not an afterthought. Plan for 4 to 8 weeks of additional development on top of your existing React Native app, depending on complexity. A simple notification-mirroring watch app takes 2 to 3 weeks. A full workout tracking companion with complications and tiles takes 6 to 8 weeks. Budget $15K to $40K depending on the feature set and whether you need both platforms.

Architecture: How the Phone and Watch Actually Talk

The core architecture is straightforward once you see it. Your React Native app runs JavaScript on the phone. A native module (written in Swift on iOS or Kotlin on Android) bridges between the JS runtime and the platform's watch communication API. The watch app is 100% native. Data flows in both directions through structured messages.

Watch Connectivity on iOS

Apple's Watch Connectivity framework (WCSession) provides three communication channels between the iPhone and Apple Watch:

  • Application Context: Send a dictionary of the latest app state. Only the most recent data is delivered. Perfect for updating the watch face complication or syncing user preferences. This works even when the counterpart app is not running.
  • User Info Transfer: Queue data that gets delivered in order. Good for syncing historical records like completed workouts or medication logs. Items are delivered sequentially and none are dropped.
  • Interactive Messaging: Real-time, bidirectional messaging when both apps are reachable. Use this for live workout data, sending commands from watch to phone (like "start recording"), or fetching fresh data on demand. Requires both apps to be in the foreground or the watch app to be in an active session.

The library react-native-watch-connectivity wraps WCSession for React Native. It exposes methods like sendMessage, updateApplicationContext, and transferUserInfo directly from your JavaScript code. For most use cases, this library gets you 80% of the way there. Install it, set up the WCSession delegate on the watch side, and you can push data from your RN app to the watch in under an hour.

Data Layer API on Android

Google's Wearable Data Layer API (part of Google Play Services) provides a similar set of tools for WearOS communication:

  • DataItems: Synced storage that automatically propagates changes between phone and watch. Similar to Application Context but with automatic conflict resolution and persistence.
  • Messages: Fire-and-forget messages for one-way communication. Lower overhead than DataItems but no delivery guarantee if the counterpart is disconnected.
  • Channel API: Stream large data transfers (audio files, workout maps, images) between devices without loading everything into memory.

There is no established React Native library for the WearOS Data Layer API that matches the maturity of react-native-watch-connectivity. You will need to write a custom native module in Kotlin that wraps the DataClient, MessageClient, and CapabilityClient APIs. If you are using the new architecture with Turbo Modules, this is the right approach anyway because you get synchronous native method calls and typed interfaces through the codegen.

The Bridging Layer

Your native module is the translator between two worlds. On the React Native side, it exposes a JavaScript API like WatchBridge.sendWorkoutUpdate({heartRate: 142, elapsed: 1800}). On the native side, it serializes that data and pushes it through WCSession or DataClient. Events coming from the watch (like a button tap or a complication refresh request) flow the opposite direction: native listener catches the event, emits it through the RN bridge, and your JS code handles the business logic.

Keep the bridge thin. Do not try to proxy complex UI state. The watch app should own its own view layer completely. The bridge should only carry data payloads and commands.

Building the Watch UI: SwiftUI and Jetpack Compose

Watch UIs are radically constrained, and that constraint is actually freeing. You do not need to worry about complex layouts, navigation stacks, or animation libraries. You need a handful of screens that display data clearly at a glance.

SwiftUI for watchOS

Apple Watch apps are built exclusively with SwiftUI since watchOS 7. The good news is SwiftUI is genuinely pleasant for watch development. A typical watch app has 3 to 5 views total. Here is what a fitness companion might include:

  • Main dashboard: Current heart rate, step count, active calories. A single scrollable view with large, readable numbers.
  • Workout view: Elapsed time, current pace, heart rate zone indicator. This view stays on-screen during active workout sessions using HKWorkoutSession.
  • History list: Recent workouts or medication doses. A simple List with NavigationLink to detail views.
  • Settings: Toggle notifications, set goals, configure complication data source.

The Apple Watch screen is 396x484 pixels on the Series 10 (45mm). Text needs to be at minimum 16pt to be readable. Use SF Rounded or the system font. Avoid custom fonts because they waste memory and load slowly on the watch's limited hardware.

Jetpack Compose for WearOS

WearOS uses Jetpack Compose with the Horologist library, which provides wear-specific UI components like TimeText, ScalingLazyColumn, and curved layouts for round screens. Compose for WearOS is structurally identical to Compose for phones, but the component set is different.

Key differences from phone Compose: ScalingLazyColumn replaces LazyColumn and automatically scales items as they move toward the edge of the round display. Chip replaces Button as the primary interactive element. The screen is typically 450x450 pixels on devices like the Pixel Watch 3 or Galaxy Watch 7.

Developer writing SwiftUI and Kotlin code for watch companion app integration

UI Design Rules for Watches

After building several watch companions, here are the rules I follow:

  • One primary action per screen. If the user has to think about what to tap, you have too much on screen.
  • Large tap targets. Minimum 44x44 points on Apple Watch, 48x48 dp on WearOS. Fingers are imprecise on tiny screens.
  • No text input. Ever. Use preset responses, voice dictation, or selections from a short list. Nobody wants to type on their wrist.
  • Limit scrolling. If your view scrolls more than 3 screen heights, break it into separate screens or cut content.
  • Dark backgrounds only. OLED screens on every modern watch mean black pixels are off pixels, which directly extends battery life.

Complications and Tiles: The Real Value of Watch Apps

Here is a truth most teams learn too late: the most valuable part of a watch app is not the app itself. It is the complication (watchOS) or tile (WearOS) that lives on the watch face or in the tile carousel. Users look at their watch face 100+ times per day. They open third-party watch apps maybe 2 to 3 times. If your data is on the face, you win.

watchOS Complications with WidgetKit

Since watchOS 9, complications are built using WidgetKit (the same framework as iPhone widgets). You define a TimelineProvider that returns entries with data to display, and the system renders your complication at appropriate times. Complication families include:

  • Circular: A small round element on the watch face. Show a single number or icon (step count, next medication time).
  • Rectangular: A wider format that supports a line of text and a gauge. Perfect for progress bars (daily step goal, calorie budget remaining).
  • Inline: A single line of text on the watch face. Use for short status strings like "Next dose: 2:30 PM".
  • Corner: Text and a gauge in the corner of certain watch faces.

The critical thing about complications is the timeline model. You do not update complications in real time. You provide a timeline of future entries, and the system renders them at the scheduled times. For a medication reminder app, you would generate timeline entries for each scheduled dose for the next 24 hours. For fitness, you update the timeline when new step data arrives via background refresh.

To feed data from your React Native app to the complication, push the latest state via WCSession's updateApplicationContext. On the watch side, store it in a shared App Group container that both the watch app and the WidgetKit extension can access. Then call WidgetCenter.shared.reloadAllTimelines() to trigger a complication refresh.

WearOS Tiles

WearOS Tiles are swipeable cards accessible by swiping left or right from the watch face. They are built with the Tiles API (androidx.wear.tiles) and use a layout system based on proto-layout definitions. Tiles refresh on a schedule you define (minimum 15-minute intervals for most tiles) or on demand when the user swipes to them.

Tiles support basic layouts: rows, columns, text, images, and circular progress indicators. A fitness tile might show your daily step count, distance walked, and a progress ring. Tapping the tile launches your full watch app. The Data Layer API syncs fresh data from the phone to the tile renderer on the watch.

Both complications and tiles are where your watch investment pays for itself. If you are building a wearable health app, prioritize the complication or tile over fancy in-app features.

Health Data, Workouts, and Background Refresh

If your companion app involves fitness or health, you are going to work with HealthKit on iOS and Health Connect on Android. The watch is where the sensors live, so the watch app is responsible for recording workout sessions and collecting health samples. The phone app aggregates, analyzes, and displays trends.

Workout Sessions on Apple Watch

HKWorkoutSession is the API that keeps your watch app alive during a workout. Without it, watchOS will suspend your app after a few seconds of wrist-down time. Starting a workout session gives you continuous access to heart rate, location, and motion data. It also shows the green workout indicator on the watch face so users know the session is active.

A typical flow: the user taps "Start Workout" on the watch. The watch app starts an HKWorkoutSession and an HKLiveWorkoutBuilder. Heart rate samples stream in at roughly 1-second intervals. The watch UI displays live metrics. Simultaneously, the watch sends summary updates to the phone every 5 to 10 seconds via sendMessage so your React Native app can show a live dashboard if the user opens the phone app during the workout.

When the workout ends, the watch saves the HKWorkout to HealthKit. Your React Native app can read it later using a HealthKit native module (react-native-health or a custom Turbo Module). The data automatically syncs from the watch's HealthKit store to the phone's HealthKit store via iCloud.

Health Connect on WearOS

WearOS uses Health Services API (androidx.health.services) for real-time sensor access on the watch, and Health Connect (androidx.health.connect) as the centralized health data store on the phone. The watch app requests an ExerciseClient to start a workout session, which provides continuous heart rate, steps, calories, and GPS data.

Health Connect replaced Google Fit as the standard health data platform on Android. Your React Native app interacts with Health Connect through a native module. The react-native-health-connect library provides basic read/write access, but you may need to extend it for workout-specific data types.

Background Refresh

Both platforms allow limited background execution for health apps:

  • watchOS: Background App Refresh gives you about 15 seconds of execution time at system-determined intervals (roughly every 15 to 60 minutes). Use this to update complications with fresh data from HealthKit or to sync pending data to the phone. Extended runtime sessions allow longer background execution for specific use cases like tracking a workout or monitoring a health condition.
  • WearOS: WorkManager handles background tasks. Schedule periodic sync jobs that push accumulated health data to the phone via DataClient. WearOS is less aggressive about killing background tasks than watchOS, but battery constraints mean you should still batch updates rather than sending data continuously.

The key principle: collect on the watch, process on the phone. The watch's job is to gather sensor data and send it to the phone. The phone's job is to run your business logic, call your API, and update the UI. Do not try to run complex analytics or ML models on the watch unless you absolutely must. For most fitness app use cases, the phone has 10x the processing power and 5x the battery budget.

Notifications: Mirroring vs Custom Watch Notifications

Notifications are often the first watch feature teams implement because they require the least additional code. There are two approaches, and the right choice depends on your use case.

Notification Mirroring

By default, any notification your React Native app sends to the phone gets mirrored to a paired Apple Watch or WearOS device. The user sees the notification on their wrist, can read it, and can dismiss it. You get this for free with zero watch-side code.

Mirrored notifications are fine for informational alerts: "Your order has shipped," "New message from Sarah," "Workout summary available." The notification appears on the watch with the same title, body, and icon as the phone notification. On Apple Watch, you can include a short look (just the app icon and title) and a long look (full notification content) without writing any watch app code.

Custom Watch Notifications

When mirrored notifications are not enough, you build custom notification interfaces on the watch side. This is worthwhile when you need:

  • Interactive actions: A medication reminder that lets the user tap "Taken" or "Snooze 30 min" directly from the notification, without opening the watch app.
  • Rich content: A workout summary notification with a heart rate chart, route map, or detailed splits.
  • Complications updates: Triggering a complication refresh when a notification arrives, so the watch face immediately reflects new data.
  • Haptic patterns: Custom haptic feedback for different notification types. A gentle tap for a reminder, a strong buzz for an urgent health alert.

On watchOS, custom notification interfaces are SwiftUI views inside a WKNotificationScene. On WearOS, you use NotificationCompat.Builder with WearableExtender to add watch-specific actions and layouts.

For a medication reminder app, custom notifications are essential. The user gets a buzz on their wrist at 2:00 PM. They see "Time for Metformin 500mg." They tap "Taken." The watch sends the confirmation to the phone via Watch Connectivity. Your React Native app logs the dose, updates the medication schedule, and pushes a new complication timeline. The entire interaction takes 3 seconds and the user never pulled out their phone.

Development team collaborating on React Native and native watch app integration project

Performance and Battery: Surviving on Constrained Hardware

Watch hardware is severely limited compared to phones. The Apple Watch Series 10 has 1GB of RAM and a dual-core S10 chip roughly comparable to an A12 from 2018. The Pixel Watch 3 has 2GB of RAM and a Snapdragon W5+ Gen 1. You need to write code as if you are targeting a phone from 7 years ago, because that is essentially what you are doing.

Memory Management

watchOS will terminate your app if it exceeds approximately 80 to 100MB of memory usage. This means no large image caches, no in-memory databases, and no holding workout history arrays with thousands of entries. Load data on demand, display it, and release it. Core Data or SwiftData with batch fetching is your friend for historical data on watchOS. On WearOS, Room database with paging provides similar functionality.

Battery Optimization Strategies

  • Batch network requests. Never make individual API calls from the watch. Batch data and sync to the phone, which handles all server communication. Each network request on the watch costs roughly 100x more battery than passing data to the phone over Bluetooth.
  • Minimize screen-on time. Use the Always-On Display API (watchOS) or Ambient Mode (WearOS) to show a simplified, low-power version of your UI when the wrist is down. Reduce update frequency to once per minute in ambient mode.
  • Reduce complication refresh frequency. A complication that refreshes every 5 minutes drains noticeably more battery than one that refreshes every 30 minutes. Match the refresh interval to how frequently your data actually changes.
  • Avoid GPS on the watch when the phone is nearby. GPS is the single biggest battery drain on any watch. If the phone is reachable, pull location data from the phone instead. Only use watch GPS for independent workout tracking (running without the phone).
  • Use Bluetooth LE efficiently. Keep data payloads small. WCSession messages are limited to 65KB on watchOS. DataClient items on WearOS should stay under 100KB for reliable delivery. Compress images before transferring them to the watch.

Testing Performance

The watchOS simulator does not accurately represent real device performance. Always test on physical hardware. Battery drain issues, thermal throttling, and memory pressure behave completely differently on actual devices. Budget for at least two physical test devices per platform (one older model, one current). An Apple Watch SE and a Series 10 for watchOS. A Pixel Watch 2 and a Galaxy Watch 6 for WearOS. That is around $800 to $1,200 in test hardware.

Real-World Examples and Cost Breakdown

Let me walk through three concrete companion app scenarios with realistic timelines and cost estimates. These assume you already have a working React Native phone app and a team that includes at least one iOS and one Android native developer.

Example 1: Fitness Tracking Companion ($25K to $35K)

A running and cycling app that shows live workout metrics on the watch, records workouts independently, and displays a daily activity complication. This is the most common companion app type I see.

  • watchOS side (4 to 5 weeks): SwiftUI workout view, HKWorkoutSession integration, heart rate streaming, complication with daily progress ring, Watch Connectivity bridging, background refresh for complication updates.
  • WearOS side (4 to 5 weeks): Compose workout UI, Health Services ExerciseClient, tile with daily stats, Data Layer API bridging, WorkManager for background sync.
  • React Native bridging (1 to 2 weeks): Native modules for Watch Connectivity and Data Layer, event emitters for live workout updates, shared state management.
  • Testing and polish (1 to 2 weeks): Physical device testing, battery profiling, edge cases (Bluetooth disconnection mid-workout, phone out of range, watch restart during session).

Example 2: Medication Reminder App ($15K to $20K)

A simpler companion that delivers medication reminders as custom notifications with "Taken" and "Skip" actions, plus a complication showing the next scheduled dose.

  • watchOS (2 to 3 weeks): Custom notification interface, complication with next dose time, simple medication list view, Watch Connectivity for dose logging.
  • WearOS (2 to 3 weeks): Notification actions, tile with next dose info, basic medication list in Compose, Data Layer sync.
  • RN bridging (1 week): Simpler bridge since most logic stays on the phone. Push medication schedule updates to the watch. Receive dose confirmation events.

Example 3: Quick Actions and Remote Control ($15K to $25K)

A smart home or IoT companion that lets users trigger actions from their wrist: lock the door, adjust the thermostat, check camera feeds. No health data involved.

  • watchOS (2 to 3 weeks): Grid of action buttons, complication showing home status (locked/unlocked, current temperature), haptic confirmation on action completion.
  • WearOS (2 to 3 weeks): Chip-based action list, tile with quick actions, message-based communication with the phone for command execution.
  • RN bridging (1 to 2 weeks): Bidirectional messaging for commands and status updates. Phone handles all API calls to the smart home backend.

These estimates assume experienced developers who have built watch apps before. If your team is learning watchOS and WearOS for the first time, add 30 to 50 percent for the learning curve. SwiftUI and Compose are not difficult, but the watch-specific APIs (HKWorkoutSession, ExerciseClient, WidgetKit timelines, Tile renderers) have significant documentation gaps and edge cases that only surface on real hardware.

Getting Started: Your First Steps

If you are ready to add a watch companion to your React Native app, here is the order I recommend:

  • Start with one platform. Pick the one where most of your users are. If 70% of your audience is iOS, start with Apple Watch. Ship it, learn from it, then build WearOS. Trying to build both simultaneously doubles your unknowns.
  • Ship the complication or tile first. Before building the full watch app, ship just the complication (watchOS) or tile (WearOS) with a minimal data bridge. This delivers immediate user value and lets you validate the communication pipeline without building a full watch UI.
  • Use react-native-watch-connectivity for iOS. It is well-maintained, covers the core WCSession APIs, and saves you 1 to 2 weeks of bridging work. For WearOS, plan to write a custom Turbo Module from the start.
  • Test on physical devices from day one. Do not waste time perfecting your app in the simulator. Buy the hardware. The bugs that matter (Bluetooth timeouts, battery drain, memory pressure, thermal throttling) only appear on real watches.
  • Keep the watch app scope minimal. Every feature you add to the watch app increases maintenance cost permanently. The watch UI needs updates when watchOS or WearOS releases new versions, new device sizes launch, or APIs deprecate. Ship the minimum feature set that delivers clear value on the wrist.

Watch companion apps are one of those areas where the technical execution is not rocket science, but the product decisions matter enormously. The difference between a watch app users love and one they disable after a week comes down to showing the right information at a glance, responding to a single tap, and then getting out of the way.

If you want help building a companion watch app for your React Native project, or if you need to figure out whether the investment makes sense for your product, book a free strategy call with our team. We have shipped watch companions for fitness, health, and productivity apps and can help you scope the right approach for your specific use case.

Need help building this?

Our team has launched 50+ products for startups and ambitious brands. Let's talk about your project.

React Native watch appApple Watch developmentWearOS appcompanion appwearable development

Ready to build your product?

Book a free 15-minute strategy call. No pitch, just clarity on your next steps.

Get Started