comlink icon indicating copy to clipboard operation
comlink copied to clipboard

React Native support

Open mfulton26 opened this issue 3 years ago • 3 comments

I see #430 but it looks like any actual support for string-only messaging like React Native is experimental and/or hacky.

What would it take to get this use case officially supported and a React Native example added to the docs.

This looks like such a nice tool and I'd like to use it between my React Native app and my web app that runs inside of it via react-native-webview.

Thanks!

mfulton26 avatar Mar 06 '22 00:03 mfulton26

I've had a stab at this but I haven't had the chance to test the below code yet

import { Endpoint } from 'comlink'

interface StringEndpoint {
  postMessage(message: string): void
  addEventListener: (listener: (message: string) => void) => void
  removeEventListener: (listener: (message: string) => void) => void
  start?: () => void
}

export function stringEndpoint(sep: StringEndpoint): Endpoint {
  const listeners = new WeakMap()
  return {
    postMessage: x => sep.postMessage(JSON.stringify(x)),
    addEventListener: (_, handler) => {
      const listener = (raw: any) => {
        const data = JSON.parse(raw)
        if ('handleEvent' in handler) {
          handler.handleEvent({ data })
        } else {
          handler({ data })
        }
      }
      sep.addEventListener(listener)
      listeners.set(handler, listener)
    },
    removeEventListener: (_, handler) => {
      const listener = listeners.get(handler)
      if (!listener) return
      sep.removeEventListener(listener)
      listeners.delete(handler)
    },
    start: sep.start && sep.start.bind(sep),
  }
}

Usage:

workerEndpont and parentEndpoint must conform to StringEndpoint

// worker.ts
const Worker = { foo: () => 1 }
export type WorkerBridge = typeof Worker
Comlink.expose<WorkerBridge>(Worker, stringEndoint(parentEndpoint));

// main.ts
const worker = Comlink.wrap<WorkerBridge>(stringEndpoint(workerEndpoint));
await worker.foo()


mfbx9da4 avatar Aug 26 '22 16:08 mfbx9da4

@mfulton26 I am the author of Transporter. Transporter was heavily influenced by Comlink and officially supports React Native. For an example of using Transporter in React Native checkout this Expo Snack.

daniel-nagy avatar Jan 19 '24 18:01 daniel-nagy

Thank you for sharing @daniel-nagy; I will keep this in mind for future use cases. We moved a while ago to use GraphQL over string-based message posting and that is working nicely for us at this time (more explicit than something that looks like you're calling code directly, but it has its advantages).

mfulton26 avatar Jan 19 '24 19:01 mfulton26