Messages
Send dictionaries to the Watch for immediate delivery, and answer the ones it sends you.
A Message is a dictionary sent over the Session for immediate delivery. It only works while the Watch is reachable: the Watch app is running and in range. Check isWatchReachable before sending. To send data that waits until the Watch app can take it, use Application Context or User Info instead.
Messages travel both ways:
- Outbound (iPhone → Watch):
sendMessageasks for a Reply, andsendMessageWithoutReplydoesn't. - Inbound (Watch → iPhone):
onMessageReceivedfires for a Message that doesn't ask for a Reply, andonMessageWithReplyfires for one that does.
A Message's values must be ones WatchConnectivity can carry: strings, numbers, booleans, arrays and nested objects. Anything else fails with ERR_PAYLOAD_UNSUPPORTED_TYPES. To send raw bytes, use Data Messages.
sendMessage
sendMessage<T extends MessagePayload, R extends MessagePayload>(message: T): Promise<R>Sends a Message to the Watch and waits for its Reply.
The Watch app must receive it with a reply handler and call it, in session(_:didReceiveMessage:replyHandler:). If it never replies, the Promise rejects with ERR_MESSAGE_REPLY_TIMED_OUT.
Type parameters
| Name | Description |
|---|---|
T | The shape of the Message you send. |
R | The shape of the Reply you expect. The library doesn't check it at runtime. |
MessagePayload is Record<string, any>.
Parameters
| Name | Type | Description |
|---|---|---|
message | T | The Message to send. |
Returns Promise<R>, which resolves with the Watch's Reply.
Throws (the Promise rejects with):
| Code | When |
|---|---|
ERR_WATCH_NOT_REACHABLE | The Watch isn't reachable. Nothing was sent. |
ERR_MESSAGE_REPLY_TIMED_OUT | The Watch didn't reply in time. |
ERR_PAYLOAD_UNSUPPORTED_TYPES | The Message contains a value WatchConnectivity can't carry. |
ERR_PAYLOAD_TOO_LARGE | The Message is too large to send. |
ERR_UNSUPPORTED_PLATFORM | Called on a platform other than iOS. |
WatchConnectivity can fail with other codes too. See Error codes for the full list.
Example
import , { type } from "rn-watch-connect";
type = { : number };
type = { : number };
try {
const reply = await .<, >({ : 1 }); .(.);
} catch () {
const = ( as { ?: }).;
if ( === "ERR_WATCH_NOT_REACHABLE") {
// Try again when onReachabilityChanged says the Watch is reachable.
}
}sendMessageWithoutReply
sendMessageWithoutReply<T extends MessagePayload>(message: T): Promise<void>Sends a Message to the Watch without asking for a Reply. The Watch app receives it in session(_:didReceiveMessage:).
Type parameters
| Name | Description |
|---|---|
T | The shape of the Message you send. |
Parameters
| Name | Type | Description |
|---|---|---|
message | T | The Message to send. |
Returns Promise<void>, which resolves once the Message is handed to the Session.
Throws (the Promise rejects with):
| Code | When |
|---|---|
ERR_WATCH_NOT_REACHABLE | The Watch isn't reachable. Nothing was sent. |
ERR_UNSUPPORTED_PLATFORM | Called on a platform other than iOS. |
Its error message starts with Expo's prefix, "Calling the 'sendMessageWithoutReply' function has failed", so match on code.
Example
import from "rn-watch-connect";
if (.) {
await .({ : 42 });
}onMessageReceived
onMessageReceived: (message: MessagePayload) => voidFires when an Inbound Message arrives that doesn't ask for a Reply. The listener gets the Message itself.
Example
import { } from "expo";
import from "rn-watch-connect";
export function () {
(, "onMessageReceived", () => {
.("Score from the Watch:", .score);
});
return null;
}Outside a component, use addListener, and call remove() on the subscription when you're done:
import from "rn-watch-connect";
const = .("onMessageReceived", () => {
.();
});
.();onMessageWithReply
onMessageWithReply: (event: MessageWithReplyEvent) => voidFires when an Inbound Message arrives that asks for a Reply. Answer it by calling the event's Reply function, reply.
Event
| Field | Type | Description |
|---|---|---|
message | MessagePayload | The Message from the Watch. |
reply | (reply: MessagePayload) => Promise<void> | The Reply function: sends reply back to the Watch. |
replyId | string | Deprecated. For replyToMessage. Call reply instead. |
Each Message takes one Reply:
- If several listeners get the same Message, the first
replycall wins. Later calls reject. - A Message can stop waiting for its Reply, for example when its last listener is removed. Calling
replyafter that rejects.
reply throws (its Promise rejects with):
| Code | When |
|---|---|
ERR_REPLY_NOT_PENDING | This Message was already replied to, or is no longer waiting for a Reply. |
Example
import { } from "expo";
import from "rn-watch-connect";
export function () {
(, "onMessageWithReply", ({ , }) => {
if ("ping" in ) {
({ : .ping });
}
});
return null;
}replyToMessage
Deprecated
Call the reply function from onMessageWithReply instead.
replyToMessage still works, and will be removed in a future major version.
replyToMessage(replyId: string, reply: MessagePayload): Promise<void>Sends the Reply to an Inbound Message, using the replyId from its onMessageWithReply event.
Parameters
| Name | Type | Description |
|---|---|---|
replyId | string | The event's replyId. |
reply | MessagePayload | The Reply to send. |
Returns Promise<void>, which resolves once the Reply is sent.
Throws (the Promise rejects with):
| Code | When |
|---|---|
ERR_REPLY_NOT_PENDING | This Message was already replied to, or is no longer waiting for a Reply. |
ERR_UNSUPPORTED_PLATFORM | Called on a platform other than iOS. |
Its error message starts with Expo's prefix, "Calling the 'replyToMessage' function has failed", so match on code.
Moving to reply
// Before (deprecated)
useEventListener(RnWatchConnect, "onMessageWithReply", ({ message, replyId }) => {
RnWatchConnect.replyToMessage(replyId, { pong: message.ping });
});
// After
useEventListener(RnWatchConnect, "onMessageWithReply", ({ message, reply }) => {
reply({ pong: message.ping });
});