Skip to content

Commit

Permalink
Merge pull request #38 from ujwal-setlur/feature/doc-updates
Browse files Browse the repository at this point in the history
Doc updates for latest apollo client and react-native
  • Loading branch information
theodorDiaconu authored Dec 13, 2018
2 parents e120a2e + 61dfd38 commit 6c12c47
Showing 1 changed file with 39 additions and 45 deletions.
84 changes: 39 additions & 45 deletions docs/react-native-client.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ There are, however, a few things to keep in mind:

- Authentication token is usually stored in AsyncStorage, and retrieval of the token is an asynchronous process.
- The authorization header needs to set up appropriately for both http links and websocket links.
- Some polyfills are needed
- logout function from meteor-apollo-accounts uses ```Symbol``` which is not supported on Android.

Since retrieval of the token is an asynchronous process, care must be taken to set it up appropriately for your http and websocket links. Let us first create a function to retrieve the token from AsyncStorage as a promise:

Expand Down Expand Up @@ -88,37 +88,7 @@ Now, every time the http link is used, it will query the latest login token. Thi

## WebSocket Link

Things are slightly more complicated for websocket links which are required for subscriptions:

- First, [apollo-link-ws](https://github.com/apollographql/apollo-link/tree/master/packages/apollo-link-ws) uses [subscriptions-transport-ws](https://github.com/apollographql/subscriptions-transport-ws), the latest version of which (0.9.9 as of this writing) does not support an asynchronous call to set connection parameters headers with the authorization token.
- Second, the token is sent only once when the connection is established, so if/when the token changes, the connection needs to be reestablished.

For the first issue, we need to patch [subscriptions-transport-ws](https://github.com/apollographql/subscriptions-transport-ws). Here is the patch:

```diff
patch-package
--- a/node_modules/subscriptions-transport-ws/dist/client.js
+++ b/node_modules/subscriptions-transport-ws/dist/client.js
@@ -380,9 +380,11 @@ var SubscriptionClient = (function () {
_this.clearMaxConnectTimeout();
_this.closedByUser = false;
_this.eventEmitter.emit(_this.reconnecting ? 'reconnecting' : 'connecting');
- var payload = typeof _this.connectionParams === 'function' ? _this.connectionParams() : _this.connectionParams;
- _this.sendMessage(undefined, message_types_1.default.GQL_CONNECTION_INIT, payload);
- _this.flushUnsentMessagesQueue();
+ var promise = Promise.resolve(typeof _this.connectionParams === 'function' ? _this.connectionParams() : _this.connectionParams);
+ promise.then(payload => {
+ _this.sendMessage(undefined, message_types_1.default.GQL_CONNECTION_INIT, payload);
+ _this.flushUnsentMessagesQueue();
+ })
};
this.client.onclose = function () {
if (!_this.closedByUser) {
```

You can use the excellent [patch-package](https://github.com/ds300/patch-package) to automatically apply this patch whenever you install node_modules with either "yarn" or "npm install".

Once the patch has been applied, you can set up the WebSocketLink to use an asynchronous function to set up the authorization header:
Things are slightly more complicated for websocket links which are required for subscriptions. You need to set up the WebSocketLink to use an asynchronous function to set up the authorization header since that is retrieved from AsyncStorage.

```js
// our websocket link for subscriptions
Expand Down Expand Up @@ -149,7 +119,7 @@ const wsLink = new WebSocketLink({

Now, the login token is resolved and sent to the server when the websocket connection is established.

However, we still need address the second issue where the authorization token is sent only once and not when the token changes, e.g. during logout/login. To handle this, we essentially need to bounce the websocket link:
Also, The token is sent only once when the connection is established, so if/when the token changes, the connection needs to be reestablished. To handle this, we essentially need to bounce the websocket link:

```js
wsLink.subscriptionClient.close(false, false);
Expand Down Expand Up @@ -231,10 +201,14 @@ wsLink.subscriptionClient.onConnected(_connected);
wsLink.subscriptionClient.onReconnected(_connected);
```

## Polyfills
## logout()


The ```logout()``` function from meteor-apollo-accounts uses ```Symbol``` which is not supported on Android. One option is to use a polyfill from core-js at the top of your main file:

On react-native, there are some other quirky issues. The meteor-apollo-accounts makes use of the Symbol type which is not supported on Android. A polyfill is required to handle this:


```js
// import this since android needs this to resolve
// https://github.com/orionsoft/meteor-apollo-accounts/issues/73
Expand All @@ -245,21 +219,41 @@ import 'core-js/fn/symbol/iterator';
import 'core-js/es6/set';
```

Another polyfill is needed to handle Object.setProtoypeOf() which is used by apollo-client and not supported by android:
However, this breaks on react-native 0.56.0 and triggers https://github.com/facebook/react-native/issues/18542

The safest option seems to be to use a direct mutation:

```js
// This polyfill is to address an issue on android
// Object.setProtoypeOf is not defined on android
// https://github.com/apollographql/apollo-client/issues/3236
Object.setPrototypeOf =
Object.setPrototypeOf ||
function(obj, proto) {
obj.__proto__ = proto; // eslint-disable-line no-proto
return obj;
};
let token = loginToken;
let mutation = gql`
mutation logout($token: String!) {
logout(token: $token) {
success
}
}`;

client.mutate({
mutation: mutation,
variables: {
token
}
}).then((result) => {
console.log("logout success: " + JSON.stringify(result));
storeLoginData({
userId: "",
token: "",
tokenExpires: ""
});
}).catch((error) => {
console.log("logout error: " + JSON.stringify(error));
storeLoginData({
userId: "",
token: "",
tokenExpires: ""
});
});
```

Do both of these at the top of your main application file.

This should get you functional on react-native!

Expand Down

0 comments on commit 6c12c47

Please sign in to comment.