Skip to content

Conversation

chukitow
Copy link
Contributor

The API for WebSockets on React Native it's similar to the Web API but actionable is not supported given it makes some references to the DOM.

I noticed its possible to make it compatible with React Native by ignoring those DOM references in order to don't get errors like #35674

@simi
Copy link
Contributor

simi commented Jul 10, 2019

Wouldn't it be better to create custom ActionCable implementation (custom npm package, ...) aimed to React native only?

@jeremy jeremy requested a review from javan July 10, 2019 22:45
@javan
Copy link
Contributor

javan commented Jul 11, 2019

Thanks for taking a crack at this, @chukitow!

Currently, action_cable.js is only supported in browsers. We made a small change in #34941 that allowed it to run in Web Workers without guaranteeing compatibility going forward.

I'm open to supporting other environments, but not without a CI-compatible test suite for each, and we're currently only set up for browser testing. Is that something you're interested in exploring?

Closing for now. Thanks again!

@Rudiney
Copy link

Rudiney commented Jul 9, 2020

Hey folks, just want to drop here that i found fairy simple to have this working today with React Native and Expo by working around 2 main problems:

  1. The wierd fix for IE using document to create an A element to replace the socket url from http to ws
  2. Global usage of browser's event system

Here is how i managed to use @rails/actioncable js package(v6.0.3-2) in a React Native(v16.9) project with Expo(SDK v37) to connect to a Rails 6 backend:

  1. Make sure you create the consumer sending an URL that already starts with ws or wss. (To bypass the wierd IE fix)
  2. Add a global replay for addEventListener and removeEventListener. I used react-native-event-listeners

Show me tha code:

import { createConsumer } from "@rails/actioncable";
import { EventRegister } from "react-native-event-listeners";

global.addEventListener = EventRegister.addEventListener;
global.removeEventListener = EventRegister.removeEventListener;

class WsNotificationsHandler extends React.Component {
  componentDidMount() {
    this._connect();
  }

  componentWillUnmount() {
    this._disconnect();
  }

  _connect() {
    const cable = createConsumer(`wss://YOURRAILSURL.com/cable?token=${access_token}`);
    this.channel = cable.subscriptions.create("NotificationsChannel", {
      received: this._gotNotification,
      //... 
    });
  }

  _gotNotification = (payload) => {
    console.log("BOOM! Notification:", payload)
  };

  _disconnect() {
    this.channel?.unsubscribe?.();
  }

  render() {
    return null
  }
}

here are the versions at my package.json:

"@rails/actioncable": "^6.0.3-2",
"react-native-event-listeners": "^1.0.7",
"react-native": "https://github.com/expo/react-native/archive/sdk-37.0.1.tar.gz",
"expo": "^37.0.0",

As far as i could get, the only side effect with "mocking" the global event system is that we lost @rails/actioncable handling of stale conections for not visible browsers tab. But that shouldnt be a problem.

Hope that helps!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants