pusher / pusher-websocket-react-native

React Native official Pusher SDK
MIT License
62 stars 55 forks source link

RCTCallableJSModules is not set #85

Closed Bayramito closed 1 year ago

Bayramito commented 1 year ago

This is a very weird situation because it happens very rare but causes app to crash.

Ekran Resmi 2023-04-11 12 52 32

fbenevides commented 1 year ago

Hi @Bayramito, which version are you using?

Bayramito commented 1 year ago

Hi @Bayramito, which version are you using?

1.2.1

Bayramito commented 1 year ago

Ekran Resmi 2023-04-11 14 53 14 rest of the Screenshot

Bayramito commented 1 year ago

any progress ?

benw-pusher commented 1 year ago

could you share your onEvent and onError handlers?

Bayramito commented 1 year ago

Of course @benw-pusher First of all i use MobX as state manager in my project

this is how my initialization looks like

i run this in a async componentDidMount in App.JS

        pusher.init({
          apiKey,
          cluster,
          activityTimeout: 30000,
          pongTimeout: 30000,
          onAuthorizer: onAuthorizer(this.stores),
          onConnectionStateChange: state => {
            if (state === "connected") {
              this.stores.pusher.isConnected = true;
            } else if (state === "disconnected" || state === "failed") {
              this.stores.pusher.isConnected = false;
            }
            console.log("PUSHER CONNECTION STATE:", state);
          },
          onError: error => {
            if (error.code === 400 || error.code === 401) {
              pusher.disconnect();
            }
            console.log("PUSHER ERROR", error);
          },
        });

HERE IS THE SUBSCRIPTION

/*==========================================================================
         SUBSCRIBE TO PUSHER INSTANCE
  ==========================================================================*/
  @action subscribePusherInstance = () => {
    if (!this.contactId || this.isConnected) {
      console.log("PUSHER ALREADY CONNECTED OR NO CONTACT ID, EXITING");
      return;
    }

    // if alredy subscribed, unsubscribe first
    if (pusher.connectionState === "CONNECTED") {
      this.unsubscribePusherInstance().catch(console.warn);
    }

    pusher
      .connect()
      .then(r => {
        return pusher.subscribe({
          channelName: channelName + this.contactId,
          eventName,
          onEvent: this.onEvent,
          onSubscriptionSucceeded: this.onSubscriptionSucceeded,
          onSubscriptionFailed: this.onSubscriptionFailed,
          onMemberAdded: this.onMemberAdded,
          onMemberRemoved: this.onMemberRemoved,
          onSubscriptionError: this.onSubscriptionError,
        });
      })
      .then(r => {
        // if (r.channelName && r.channelName === channelName + this.contactId) {
        //   this.isConnected = true;
        // }
      })
      .catch(console.warn);
  };

HERE IS THE UNSUBSCRIPTION

  /*==========================================================================
        UNSUBSCRIBE FROM PUSHER INSTANCE
   ==========================================================================*/
  @action unsubscribePusherInstance = () => {
    if (!this.contactId) return;
    return pusher
      .unsubscribe({channelName: channelName + this.contactId})
      .then(r => {
        this.isConnected = false;
        // return pusher.disconnect();
      })
      .catch(console.warn);
  };

and, i handle subscribing and unsusbscribing actions in my separate store related to Pusher.

@action onEvent = data => {
    const {eventName, data: eventData} = data;
    const parseData = JSON.parse(eventData);
    console.log("PUSHER EVENT", parseData);
    switch (eventName) {
      case "new-message":
        this.stores.app.pubSub.pub("new-chat-message", parseData.data);
        break;

      case "client-typing":
        this.typing = parseData.typing;
        clearTimeout(this.typingTimeout);
        if (parseData.typing) {
          this.typingTimeout = setTimeout(() => {
            this.typing = false;
          }, 2000);
        }
        break;

      default:
        console.log("UNKNOWN EVENT", data);
        break;
    }
  };

what i do here is, i have a in app EventEmitting system created by Mutex which is waiting and event to trigger itself. Basicaly this is waiting an event to happen, and if this happens updates the components that are subscribed to this event. pubSub.pub is publishing and in the components subscribing to that...

Finally this is the trigger method that i created


  @action trigger = async (eventName, payload) => {
    if (this.typing) return;
    try {
      await pusher.trigger(
        new PusherEvent({
          channelName: channelName + this.contactId,
          eventName: `client-${eventName}`,
          data: JSON.stringify(payload),
        }),
      );
    } catch (e) {
      console.log("ERROR: " + e);
    }
  };
benw-pusher commented 1 year ago

I've raised this internally for the team to investigate.

Kieraano commented 1 year ago

Any luck with this one? I'm getting the same issue where the app regularly crashes with this error.

adesugbaa commented 1 year ago

Any progress on this issue. I just switched to this library, and the iOS is constantly crashing even though I did not implement onConnectionStateChange.

[CoreFoundation] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Error when sending event: PusherReactNative:onConnectionStateChange with body: { currentState = disconnected; previousState = connected; }. RCTCallableJSModules is not set. This is probably because you've explicitly synthesized the RCTCallableJSModules in PusherWebsocketReactNative, even though it's inherited from RCTEventEmitter.' *** First throw call stack: ( 0 CoreFoundation 0x0000000180465ef8 __exceptionPreprocess + 172 1 libobjc.A.dylib 0x000000018005c0ac objc_exception_throw + 56 2 Foundation 0x0000000180caa400 -[NSMutableDictionary(NSMutableDictionary) classForCoder] + 0 3 Terminoxx360 0x00000001030e95f8 -[RCTEventEmitter sendEventWithName:body:] + 380 4 Terminoxx360 0x00000001035310b4 $s29pusher_websocket_react_native26PusherWebsocketReactNativeC8callback33_EB6D8C1094D7B<…>

fbenevides commented 1 year ago

We have released 1.3.0, which fixes this issue. Could you please check it @Bayramito?