Migrating from 1.x to 2.0
What an app on rn-watch-connect 1.x must change, and what it can change, to move to 2.0.
Most apps need three things: the new requirements, one renamed field, and a check of the behaviour changes below. Everything else is optional.
1. Update the requirements
2.0 needs Expo SDK 57 or later (React Native 0.86+) and iOS 16.4 or later. If your app must stay on an older SDK or support iOS 15, stay on rn-watch-connect@1.x.
npm install rn-watch-connect@2This is a native change, so rebuild the native app, for example with npx expo run:ios or a new development build. A JS reload isn't enough.
2. Fix the breaking change
Rename the transferFile progress keys
transferFile now returns the same progress keys as outstandingFileTransfers and the FileTransfer type. Rename total and completed wherever you read them.
// Before (1.x)
const { progress } = RnWatchConnect.transferFile(uri);
console.log(progress.completed, "of", progress.total);// After (2.0)
const { } = .();
.(., "of", .);3. Check these behaviour changes
Status events no longer fire when a listener is added
In 1.x, a new listener for onReachabilityChanged, onWatchPairedChanged or onWatchAppInstallChanged was called right away with the current value. In 2.0 they fire only on a real change, so read the property for the starting value. With useEvent, pass it as the initial value:
// Before (1.x): relied on the event firing at once
const event = useEvent(RnWatchConnect, "onReachabilityChanged");
const isWatchReachable = event?.isWatchReachable ?? false; // After (2.0): seed from the property
const { } = (, "onReachabilityChanged", {
: .,
});
The same goes for the other events: they no longer replay the last value, or an empty {}, when you add a listener. If you filtered out those empty events, you can remove that code. See Watch status.
Match errors on code, not on message
In 1.x, almost every failure had code: "ERR_UNEXPECTED". In 2.0 each failure has its own Error code, such as ERR_WATCH_NOT_REACHABLE or ERR_INVALID_TRANSFER_ID. On platforms other than iOS, the code is ERR_UNSUPPORTED_PLATFORM.
Messages changed too. Functions that throw directly now get Expo's prefix, "Calling the '…' function has failed → Caused by: …". These are sendMessageWithoutReply, sendDataMessageWithoutReply, replyToMessage, replyToDataMessage, updateApplicationContext, transferFile, cancelUserInfoTransfer and cancelFileTransfer. If you matched on message text, match on code instead:
// Before (1.x)
if (String(error).includes("not reachable")) { /* … */ }// After (2.0)
if (( as { ?: }). === "ERR_WATCH_NOT_REACHABLE") {
// …
}The reply error has a new message
Replying twice, or after a Message stopped waiting, now fails with "Already replied, or the message is no longer waiting for a Reply" instead of "Invalid reply ID". Match on its code, ERR_REPLY_NOT_PENDING.
transferUserInfo returns the full Transfer snapshot
It now includes userInfo, the same shape as outstandingUserInfoTransfers. Its type is OutstandingUserInfoTransfer. The old name, UserInfoTransfer, is a deprecated alias, so existing code still compiles.
Stricter TypeScript types
These are type changes only, with no runtime effect:
watchActivationStateis nowWatchActivationState("notActivated" | "inactive" | "activated" | "unknown") instead ofstring. A comparison against a misspelled value now fails to compile.applicationContext,receivedApplicationContext, and whatonMessageReceived,onMessageWithReply,onApplicationContextChangedandonUserInfoReceivedsend are nowRecord<string, any>instead ofany.
Fixes that may touch your code
- Status event keys.
onReachabilityChanged,onWatchPairedChangedandonWatchAppInstallChangednow send the documented keys{ isWatchReachable },{ isWatchPaired }and{ isWatchAppInstalled }. If you read the old keys (isReachable,isPaired,isAppInstalled) as a workaround, switch to the documented ones. watchActivationStateoff iOS. It's now"unknown"on platforms other than iOS, instead of"notActivated".- Received files. They no longer overwrite each other. A taken name is numbered, as in
photo(1).jpg. SeeonFileReceived. - Transfer ids. They're now unique for the whole app run, but still valid only for the current run.
4. Move off the deprecated reply methods (optional)
replyToMessage, replyToDataMessage and the events' replyId still work, and will be removed in a future major version. Call the event's Reply function, reply, instead:
// Before (deprecated)
useEventListener(RnWatchConnect, "onMessageWithReply", ({ message, replyId }) => {
RnWatchConnect.replyToMessage(replyId, { ok: true });
}); // After
(, "onMessageWithReply", ({ , }) => {
({ : true });
});
Data Messages work the same way: ({ data, reply }) => reply(base64String) replaces replyToDataMessage(replyId, base64String). See Messages and Data Messages.
5. Use what's new (optional)
- Finish events.
onUserInfoTransferFinishedandonFileTransferFinishedfire exactly once per Transfer, when it's delivered, fails or is cancelled. onFileReceiveFailed. Tells you when a file from the Watch couldn't be kept. In 1.x it was lost without any event.- The
replyfunction ononMessageWithReplyandonDataMessageWithReply(see step 4). WatchConnectErrorCode. The TypeScript union of every Error code.