Open ortutay opened 9 years ago
I actually just tried to do this yesterday. I should have posted something about it. Try running this:
$ npm install buffer --save
And then add this to the top of the first javascript file you run (like index.ios.js):
global.Buffer = global.Buffer || require('buffer').Buffer;
Also, I think you'll need to require('react-rethinkdb/dist/node')
instead of require('react-rethinkdb')
since it's not running in a browser environment.
However, after I did all that, I ran into errors about some unknown http
module, and didn't have enough time to resolve that yet. Let me know if you run into the same thing, or something else first, or find a way around it.
That solves this issue, thanks.
I still wasn't able to get this to work in React Native though. It seems like rethinkdb requires a few node core modules ('net' and 'tls') which React Native doesn't provide. Haven't figured out how to get past that yet...
Oh I think I know how to deal with those. I can try making a react native distribution that stubs net and tls modules, and http too if that helps. I'll try to get that by tomorrow, thanks for helping to test this! On Sep 11, 2015 6:06 PM, "ortutay" notifications@github.com wrote:
That solves this issue, thanks.
I still wasn't able to get this to work in React Native though. It seems like rethinkdb requires a few node core modules ('net' and 'tls') which React Native doesn't provide. Haven't figured out how to get past that yet...
— Reply to this email directly or view it on GitHub https://github.com/mikemintz/react-rethinkdb/issues/11#issuecomment-139694481 .
Great, thanks!
Actually I think it might be because the nodejs websocket library won't work in react native. So I think it makes sense to use the original require statement for the browser version of react-rethinkdb, and get window,WebSocket defined using this polyfill: https://github.com/facebook/react-native/pull/890
I'll try it tomorrow but if you want to try sooner you can see if that polyfill works for you. On Sep 11, 2015 7:16 PM, "ortutay" notifications@github.com wrote:
Great, thanks!
— Reply to this email directly or view it on GitHub https://github.com/mikemintz/react-rethinkdb/issues/11#issuecomment-139702846 .
Unfortunately, I can't get the latest version of react-native to work easily, since it looks like it requires a newer xcode, which isn't available for os x 10.9.
Can you see if you can get the react-native websocket polyfill to work? You'll know it's working if you add console.log('ws', window.WebSocket)
and it says something other than "ws undefined" in the xcode log.
And if that's working, then in theory the browser version require('react-rethinkdb')
is the one that should work in react-native, since it doesn't depend on anything fancy other than websockets.
But I think the Buffer issue is actually telling, because browsers don't natively support Buffer either. Somehow the webpack build for rethinkdb-websocket-client is properly polyfilling Buffer for browsers, but it's not working for react-native. I'll try to look into that, but it'll be hard to debug until I get set up with a newer version of os x.
If you use require('react-rethinkdb')
and the Buffer workaround above, what errors do you get?
Okay I think I understand the issue. In addition to having to polyfill window.WebSocket, which is apparently supported via https://github.com/facebook/react-native/pull/890 , we have to replicate webpack's shims that it offers via https://github.com/webpack/node-libs-browser
I'm not sure what the best practice way of doing that is for react-native, and it looks like there's an open issue for it here https://github.com/facebook/react-native/issues/1871
The Buffer workaround above is good, since it's a global. But the missing modules will mean we have to override what require
does, and I'm unfamiliar with how that's set up in react-native. If you want to try https://github.com/mjohnston/react-native-webpack-server that might just work, but that might require completely changing your build process.
Does react-rethinkdb
depend on the rethinkdb
package? rethinkdb
uses net
and tls
modules, which I think are not available in React Native.
Logging out Buffer via the workaround you provided seems to work and show something that looks correct, but using the same approach for net
and tls
gives undefined in both cases. I'll take a look at the solutions you linked above to see if it solve the problem.
Yes, react-rethinkdb
depends indirectly on rethinkdb
. But if you use require('react-rethinkdb')
instead of require('react-rethinkdb/dist/node')
it will use a patched version that doesn't depend on net
or tls
. Which require are you using that gives you the net
and tls
errors?
The approach for Buffer
works because you can override the Buffer
global variable with plain javascript, but net
and tls
are modules that can only be overridden with the help of the build system.
I believe if you use require('react-rethinkdb')
, you shouldn't get net
or tls
errors.
Also, if you want to simplify the problem, you can try using rethinkdb-websocket-client
by itself, which is what react-rethinkdb
depends on and is likely what's causing the issues. Just npm install rethinkdb-websocket-client --save
and copy/paste the example in the README to the bottom of your index.ios.js file from https://github.com/mikemintz/rethinkdb-websocket-client#how-do-i-use-this
Currently on iOS, this is blocked on react-native ArrayBuffer support:
On android, this is blocked on react-native WebSocket support:
When ArrayBuffers and WebSockets are working in react-native, react-rethinkdb should work with:
$ npm install events buffer --save
global.Buffer = global.Buffer || require('buffer').Buffer;
var ReactRethinkdb = require('react-rethinkdb');
RN Android WebSockets are now in master. I don't think anyone has really stress-tested them if you want to give it a shot.
Not much to add other than using ReactDB as backend for React Native is exactly what I'm looking for. Hopefully the blockers get resolved!
On iOS ArrayBuffer support in RN. Looks like it's been resolved and merged? https://github.com/facebook/react-native/pull/4483
@fungilation Yes I think that's the case. I saw that merge and tested it on react-native for android but turns out it was only implemented for iOS. Has anyone been able to test since then with iOS?
I'll report after I setup my app and test, I have Mac and xcode
Thanks! Let me know if you run into any issues, so far I've been able to work around everything other than "array buffer not supported on this platform"
Hi, It seems like there is no web socket implementation:
sendArrayBufferImpl(): void {
// TODO
console.warn('Sending ArrayBuffers is not yet supported');
}
nothing is sent to server
https://github.com/facebook/react-native/blob/master/Libraries/WebSocket/WebSocket.js
Interesting, I guess they implemented receiving ArrayBuffers but not sending.
I think the most practical way forward is to add support in rethinkdb-websocket-client and rethinkdb-websocket-server for base64 string websocket messages. It shouldn't replace binary as the default, but that would be great if it allows react-native to work. I'll look into that.
I added a base64 option to rethinkdb-websocket-client and rethinkdb-websocket-server, which works fine in the browser.
Unfortunately, react-native android seems to ignore WebSocket sub-protocols. I just reported it as https://github.com/facebook/react-native/issues/5810. But when I hard-code both the client and server to use base64 instead of negotiating the protocol, it works!
The iOS code looks like it respects WebSocket sub-protocols, so it should work without hard-coding client and server to base64.
If anyone wants to try it on iOS with latest master from rethinkdb-websocket-client and rethinkdb-websocket-server, setting wsProtocols: ['base64']
in RethinkdbWebsocketClient.connect()
, that'd be nice to know if it works there. I'll probably push out a version of react-rethinkdb tonight that exposes wsProtocols
so the whole thing should work on iOS.
If you use the latest versions (react-rethinkdb 0.5.4 and rethinkdb-websocket-server 0.3.6), you should be able to use base64 websockets by specifying wsProtocols: ['base64']
in RethinkSession.connect()
.
@xaviercobain88 and @fungilation, could you see if this works for you with react-native for iOS?
I was able to test on react-native for iOS on a Mac today, and found similar missing functionality in react-native's WebSocket implementation (it doesn't expose the sub-protocols information), which I just reported at https://github.com/facebook/react-native/issues/6137.
Ideally we should resolve the WebSocket issues in react-native instead of working around them here. But since they may be time consuming to get working there, I propose we create an unofficial flag here to get things working in the meantime. I'll add something like forceBase64WebSockets
in react-rethinkdb, rethinkdb-websocket-client, and rethinkdb-websocket-server, so when it's enabled we completely disregard the negotiated sub-protocol.
+1 Just got in. I believe it is really an excited feature for react native and rethinkdb!
Any update? Is there a definite way to make this work in RN?
@mikemintz I'm using React-Native=0.29, rethinkdb-websocket-server=0.6.0 and react-rethinkdb=0.6.0. I'm using wsProtocols: ['base64']
in the client. Do I need to do something similar in the server?
I'm getting "list" argument must be an Array of Buffers in WebSocket.ws.onmessage when it tries to do Buffer.concat
@GeoffreyPlitt is this resolved by your fix in https://github.com/mikemintz/rethinkdb-websocket-client/issues/9#issuecomment-237993464 ?
No, I didn't get things working yet. I've gotten past one error, but having another.
It's not clear to me from your messages above, did anyone get this working with RN or not? Can that code be posted so I can see how this works correctly, at least in theory?
What is the current documented issue with getting this to work with RN?
Same as OP. "Buffer is not defined". There are a handful of other global modules that browsers have but ReactNative doesn't have.
Sorry I missed some of these messages.
I was able to work around "Buffer is not defined" with
$ npm install buffer --save
global.Buffer = global.Buffer || require('buffer').Buffer;
Since the issues I reported to react-native regarding websocket protocols look like they still haven't been resolved, I was only able to get it to work by locally modifying both rethinkdb-websocket-client and rethinkdb-websocket-server to force base64 regardless of the protocol agreed upon.
See these commits for the relevant lines
this.webSocket.protocol === 'base64'
with true
)ws.protocol === 'base64'
with true
)Note, it's not enough to set wsProtocols: ['base64']
in client, since that just determines what is sent to the server during negotiation.
Ideally this would be fixed in react-native's implementation of websocket (refer to the github issues I reported in the comments above). But in the meantime, if you need to use this without local modification, feel free to submit a PR with a hidden flag like forceBase64WebSockets
Other than adding hard-coding true
in the rethinkdb-websocket-server/client code, here's some code I believe I was able to get working with android back on Feb 7:
package.json
{
"name": "reactnativeandroidtest3",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start"
},
"dependencies": {
"buffer": "^4.0.0",
"events": "^1.1.0",
"react-native": "^0.25.1",
"rethinkdb-websocket-client": "^0.4.6"
}
}
Bottom of index.android.js
global.Buffer = require('buffer').Buffer;
var RethinkdbWebsocketClient = require('rethinkdb-websocket-client');
var r = RethinkdbWebsocketClient.rethinkdb;
var options = {
host: '12d1ffa.ngrok.com',
port: 80,
path: '/db',
wsProtocols: ['base64'],
secure: false,
db: 'test',
};
console.log("yay0");
RethinkdbWebsocketClient.connect(options).then(function(conn) {
console.log("yay1");
var query = r.table('turtles');
query.run(conn, function(err, cursor) {
console.log("yay2");
cursor.toArray(function(err, results) {
console.log("yay3");
console.log(results);
});
});
}, function(e) {console.log("boo", e)});
Hey @mikemintz, thanks I'll play around with it this evening. This might be worth a look--FeatherJS within RN. They use Socket.io
http://docs.feathersjs.com/clients/feathers.html#usage-with-react-native
Made the suggest change to rethinkdb-websocket-client
npm run test
Uncaught TypeError: "list" argument must be an Array of Buffers
The unit tests for rethinkdb-websocket-client are written assuming that the backend sends binary frames, not base64. I wouldn't worry that it's not passing, the code changes are just a workaround to force base64 no matter what on both ends.
Using the hacked version as implied above: I setup a control on the browser. It works on the browser only if i DON'T pass wsProtocols: ['base64']
. If I do I get the same error as the unit test.
Does not work on Android. Server never sees request. No errors on console, just 'yay0' and that's it.
Think you could create a repository to work on this and post your working code?
Thanks.
I believe I have iOS working right now. Please share working prototype for Android. Almost there...
Now working for me on both Android and iOS. 👍
Had a chance to play around with this project some more last night. My problem revolved around the way RN Android routes traffic.
I didn't see this documented over at React-Native anywhere but the Android implementation of React Native seems to meddle with traffic over localhost
. It also works in a way that effectively ignores /etc/hosts
Reverse proxy/Ngrok isn't strictly needed however (helpful for device testing for sure). When using Genymotion one can just use a different IP to reach the local machine (ie, 192.168...) and it should work with Android since straight up "localhost" doesn't, at least not for me.
🍷 To me, working with Rethink directly client-side offers a nicer API than Meteor's minimongo. The whitelist validation method is more intuitive. I've not seen or have been able to use minimongo in RN, its very tied to a browser environment. It's interesting that Rethink's Horizon has an API closer to Mongo than Rethink.
--- EDIT ---
Come to think of it, the localhost issue makes sense now because Genymotion's virtualization would have its own localhost.
Good to know on comparing with minimongo. I switched to react native now as meteor was inadequate for mobile. Considering backend and Realm is the forerunner so far On Fri, Aug 26, 2016 at 9:51 AM Babak notifications@github.com wrote:
Now working for me on both Android and iOS. 👍
Had a chance to play around with this project some more last night. My problem revolved around the way RN Android routes traffic.
I didn't see this documented over at React-Native anywhere but the Android implementation of React Native seems to not like 'localhost' or '127.0.0.1'. It also works in a way that effectively ignores /etc/hosts
Reverse proxy/Ngrok isn't strictly needed however (helpful for device testing for sure). When using Genymotion one can just use a different IP to reach the local machine (ie, 192.168...) and it should work with Android since straight up "localhost" doesn't, at least not for me.
🍷 To me, working with Rethink directly client-side offers a nicer API than Meteor's minimongo. The whitelist validation method is more intuitive. I've not seen or have been able to use minimongo in RN, its very tied to a browser environment. It's interesting that Rethink's Horizon has an API closer to Mongo than Rethink.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/mikemintz/react-rethinkdb/issues/11#issuecomment-242789056, or mute the thread https://github.com/notifications/unsubscribe-auth/ADoJShUKb51cKlvMYQf9X-FmktAxPoUwks5qjxl3gaJpZM4F8HcK .
@fungilation Thanks for the heads up on Realm. Seems like a great solution for local storage.
Ya. For centralised data store, a sync between Realm <-> Firebase would be interesting On Fri, Aug 26, 2016 at 1:28 PM Babak notifications@github.com wrote:
@fungilation https://github.com/fungilation Thanks for the heads up on Realm. Seems like a great solution for local storage.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/mikemintz/react-rethinkdb/issues/11#issuecomment-242842954, or mute the thread https://github.com/notifications/unsubscribe-auth/ADoJSl2-ptIRLYZ6lHD0NziHQsL-iPUAks5qj0xUgaJpZM4F8HcK .
Pull request in 🤖
https://github.com/mikemintz/rethinkdb-websocket-client/pull/14
This PR should be all that is needed for base64
websocket. rethinkdb-websocket-server
doesn't need any changes as of RN 0.32 (and perhaps previous versions). I don't believe react-rethinkdb
would need to be patched either.
Nice! On Sat, Aug 27, 2016 at 2:47 AM Babak notifications@github.com wrote:
Pull request in 🤖
mikemintz/rethinkdb-websocket-client#14 https://github.com/mikemintz/rethinkdb-websocket-client/pull/14
This PR should be all that is needed for base64 websocket. rethinkdb-websocket-server doesn't need any changes as of RN 0.32 (and perhaps previous versions). I don't believe react-rethinkdb would need to be patched either.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/mikemintz/react-rethinkdb/issues/11#issuecomment-242907703, or mute the thread https://github.com/notifications/unsubscribe-auth/ADoJSuxqfhnhGpKyUcNSBjRf24dDhycsks5qkAeygaJpZM4F8HcK .
Sweet! It's been a week, can we merge this?
This was merged and published a week ago, so it should work on the latest version from npm.
Doh, sorry, thought this was a PR, not an issue.
No worries. I think the latest library works, but you still need to use this (below) in your client code. If you get a chance to try it out too, let us know if there are any issues.
$ npm install buffer --save
global.Buffer = global.Buffer || require('buffer').Buffer;
@mikemintz On my end its not yet published on npm.
npm install rethinkdb-websocket-client
vi node_modules/rethinkdb-websocket-client/dist/index.js
ws.onerror = function (event) {
emitter.emit('error', event);
};
ws.onmessage = function (event) {
var data = event.data;
if (typeof Blob !== 'undefined' && data instanceof Blob) {
(0, _blobToBuffer2['default'])(data, function (err, buffer) {
if (err) {
throw err;
}
emitter.emit('data', buffer);
});
} else if (typeof data === 'string' && ws.protocol === 'base64') {
emitter.emit('data', new Buffer(data, 'base64'));
} else {
emitter.emit('data', data);
}
};
};
How does one listen for the error being emitted via emitter.emit('error', event);
. In React Native, interrupted connections can throw an error that trace back to this statement.
Error handling with rethinkdb-websocket-client
should work as this:
r.table('marvel').run(conn).then(function(cursor) {
return cursor.toArray()
}).then(function(results) {
// process the results
}).catch(function(err) {
// process error
})
https://www.rethinkdb.com/api/javascript/run/
Haven't yet tested. I'll follow up. Otherwise disconnecting even briefly will cause the infamous "red screen of death".
These are two different origins for exceptions btw. The first is when ws
raises an exception the second is when this patched driver does.
@babakness good catch, I don't know why the publish didn't work for 0.5.0. I just republished as 0.5.1 and the changes should be there now.
I'm not quite sure what you're asking about the error handling. I think the emitter.emit('error', event)
code should just be making websocket errors propagate as if they happened on the fake TCP socket. Are you saying that you think ws
will raise an unhandled exception in addition to calling the onerror
callback?
@mikemintz quick update, in RN, console.warn gives an annoying toast when it should just be something in the debug console. Also, for catching the rejected connection
https://github.com/babakness/react-rethinkdb/blob/master/src/Session.js#L43 https://github.com/babakness/react-rethinkdb/blob/master/src/Session.js#L60
Without this, the uncaught reject can trigger the "red screen of death" in RN.
I'm using a modified version of this Session functionality with Redux in RN. When a connection is lost, which is a given assumption in a mobile setting, we want to delegate the adjustment to this situation to the app codebase. To accommodate this need, an additional parameter was added--a callback function that can be passed in to trigger notification of this.
While the other functionality is nice--for example the feature that reduces redundant queries--this can be delegated out to the Redux workflow so that all related queries are handled in the same place.
I've sent a PR to review.
I am going through the tutorial and I hit an error when I try to connect to the local websocket server from my React Native app. The error is:
Some relevant code: