By Timon


2015-04-02 08:34:50 8 Comments

I was working on an app with Phonegap + React.js and Socket.io. However, then React-Native got released and the native feel is amazing.

I tried getting socket.io-client working with React Native, but unfortunately without much success. I did some research and I'm getting the exact same errors as described in this issue: https://github.com/facebook/react-native/issues/375

The comments on the issue said to try and use the fetch API to fetch JS modules, but I think I'm doing this wrong:

var socketScript;    
fetch('https://cdn.socket.io/socket.io-1.2.0.js')
    .then(function(response) {
        socketScript = response._bodyText;
    }).done(function() {
        var socket = socketScript.io();
    });

This returns an undefined is not a function.

Is there any way to make socket.io-client work with React Native? Or am I looking at this the wrong way? Perhaps there are other, better suited solutions?

4 comments

@Kohver 2016-03-24 14:05:07

Now, if you want to use socket.io in your RN app, you must use this code:

if (!window.location) {
    // App is running in simulator
    window.navigator.userAgent = 'ReactNative';
}

// This must be below your `window.navigator` hack above
const io = require('socket.io-client/socket.io');
const socket = io('http://chat.feathersjs.com', {
  transports: ['websocket'] // you need to explicitly tell it to use websockets
});

socket.on('connect', () => {
  console.log('connected!');
});

Big thanks for Eric Kryski.

@Russell Maxfield 2015-08-26 18:48:54

For those like me stumbling across this question looking how to integrate socket.io with react native.

Since React Native has supported websockets for a short time now, you can now set up web sockets really easily with Socket.io. All you have to do is the following

  1. npm install socket.io-client
  2. first import react-native
  3. assign window.navigator.userAgent = 'react-native';
  4. import socket.io-client/socket.io
  5. in your constructor assign this.socket = io('localhost:3001', {jsonp: false});

So in all it should look like this after npm installing socket.io-client:

import React from 'react-native';

// ... [other imports]

import './UserAgent';

import io from 'socket.io-client/socket.io';

export default class App extends Component {
  constructor(props) {
    super(props);
    this.socket = io('localhost:3001', {jsonp: false});
  }

  // now you can use sockets with this.socket.io(...)
  // or any other functionality within socket.io!

  ...
}

and then in 'UserAgent.js':

window.navigator.userAgent = 'react-native';

Note: because ES6 module imports are hoisted, we can't make the userAgent assignment in the same file as the react-native and socket.io imports, hence the separate module.

EDIT:

The above solution should work, but in the case it doesn't try create a separate socketConfig.js file. In there import anything that is needed, including const io = require('socket.io-client/socket.io'); and having window.navigator.userAgent = 'react-native'; BEFORE requiring socket.io-client. Then you can connect your socket there and have all listeners in one place. Then actions or functions can be imported into the config file and execute when a listener receives data.

@Howard 2015-10-01 12:48:41

In my case, don't need add window.navigator.userAgent = 'react-native';, I don't know why.

@tohster 2015-10-07 21:49:41

+1 The jsonp: false configuration is important because the default value for jsonp causes socket.io to attempt manipulating the DOM (which doesn't exist in the react native environment). For search posterity, the error message triggered is: "document.createElement is not a function".

@Gabriel Matusevich 2015-11-19 13:04:26

We I send a callback (acknowledgement) from the client, the server receives the event and emits the callback but it doesn't run on my client .. do you know why is that?

@Lukas 2016-02-07 14:04:13

what react version was used with this answer? Not working with v0.19

@Russell Maxfield 2016-02-09 05:05:54

I have been using v0.19 since release and my socket still works. One thing to note is React Native now does have built in web sockets facebook.github.io/react-native/docs/network.html#websocket if you're looking for a simple socket integration.

@Dana Woodman 2016-03-04 21:58:14

The jsonp: false bit is important. Also, there seems to be no need for the user agent bit (in fact it threw errors for me saying document not defined)

@meteors 2016-05-13 15:10:53

Setting useragent gives me error Cannot set property userAgent of #<WorkerNavigator> which has only a getter

@Kelvin Aliyanto 2016-05-14 10:56:47

for some reason, my code can connect to socket in iOS simulator but not on real iPhone. any insights?

@Russell Maxfield 2016-05-18 16:02:42

@KelvinAliyanto, i would say to make sure you can actually reach the address you are trying to connect to from your phone. If you are running an express server or something similiar on your computer you may have to use something like ngrok to expose that port and url on your computer to your phone

@Krzysztof Kaczor 2016-08-28 13:42:18

You can specify explicitly transport like this: transports: ['websocket'] then you don't need jsonp: false part.

@Abundance 2017-11-06 22:34:16

For those that get an Unable to resolve module, I imported socket.io as follows: import io from 'socket.io-client/dist/socket.io';

@gayashanbc 2018-05-26 18:57:16

I'm not able to connect using this method. I'm not getting any error either. Can someone please help me?

@Colin Ramsay 2015-04-02 09:22:39

Edit Feb 2016: React Native now supports Web Sockets so some of this advice is invalid.

You've misinterpreted the Github issue I'm afraid. In it, aackerman says:

For this specific case you'll likely want to use the fetch API which is provided by the environment.

He doesn't say that you should use the fetch API to grab remote JS modules. What he's suggesting is that the fetch API be used in place of the built-in Node.JS request module, which isn't available in React Native.

Let's look at your code:

socketScript = response._bodyText;
var socket = socketScript.io();

Think about this for a second - socketScript isn't a JavaScript object, it's a string - therefore how can you call the io method on it?

What you'd really need to do is parse _bodyText before using it (in a browser you could use eval), but then you'd still have the problem that while React Native has a polyfill for XHR and the fetch API, it doesn't yet have one for the WebSocket API. Unless I'm mistaken, this means you're stuck.

I suggest opening a Github issue to request a WebSocket API polyfill and ask for the thoughts of the community. Someone might have a workaround.

@Lukas 2016-02-26 11:42:40

@Jonathan Huang 2015-04-04 23:43:21

Short of a polyfill for the WebSocket API, you can create a native module that makes use of web-sockets and send events to Javascript using eventDispatcher.

On the Javascript side, you would subscribe to these events using DeviceEventEmitter.addListener.

For more information on using native modules, see the react-native doc on the topic

@chopper draw lion4 2015-04-08 19:25:18

This should be marked as the correct answer.

@Dana Woodman 2016-03-05 00:22:03

There is a polyfill for WebSockets provided in React Native: facebook.github.io/react-native/docs/network.html#websocket

Related Questions

Sponsored Content

24 Answered Questions

[SOLVED] What is the difference between React Native and React?

4 Answered Questions

5 Answered Questions

1 Answered Questions

React native + SSL socket: Error: xhr poll error

0 Answered Questions

Socket.io and React Native, cannot emit event from phone?

2 Answered Questions

1 Answered Questions

[SOLVED] React Native with Socket.io

1 Answered Questions

[SOLVED] Socket.io client with non-socket.io server

1 Answered Questions

1 Answered Questions

[SOLVED] AngularJS : socket.io destroy socket

Sponsored Content