From 5a70116c7407f77bc6689e127ec7916943facb79 Mon Sep 17 00:00:00 2001 From: John Peterson Date: Mon, 11 May 2020 06:10:52 -0700 Subject: [PATCH 01/11] Allow other AsyncStorage packages to be used --- README.md | 21 ++++++++++++++------- docs/api.md | 5 ++++- package.json | 3 ++- src/Meteor.js | 5 ++++- src/user/User.js | 13 ++++++++----- 5 files changed, 32 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 4ed5cb3..f7a407a 100644 --- a/README.md +++ b/README.md @@ -5,16 +5,23 @@ Connect React Native to your Meteor app. Based on [react-native-meteor](https:// # Installation 1. `npm install --save meteor-react-native` -2. Confirm you have peer dependencies installed (`@react-native-community/netinfo` and `@react-native-community/async-storage>=1.8.1`) +2. Confirm you have peer dependencies installed (`@react-native-community/netinfo`) +3. An AsyncStorage library that you pass to `options` + - `import AsyncStorage from '@react-native-community/async-storage'` OR + - @react-native-community/async-storage@>=1.8.1 + - `import AsyncStorage from 'react-native'` + - If using Expo, or cannot otherwise use @react-native-community/async-storage # Basic Usage -```` -import { Meteor, Mongo, withTracker } from 'meteor-react-native'; +```javascript +import Meteor, { Mongo, withTracker } from 'meteor-react-native'; +import { AsyncStorage } from 'react-native'; // OR '@react-native-community/async-storage' + let MyCol = new Mongo.Collection("mycol"); -Meteor.connect("wss://myapp.meteor.com"); +Meteor.connect("wss://myapp.meteor.com", { AsyncStorage }); class App extends React.Component { render() { @@ -25,7 +32,7 @@ class App extends React.Component { Here is the thing: {myThing.name} ); - } + } } let AppContainer = withTracker(() => { @@ -38,9 +45,9 @@ let AppContainer = withTracker(() => { })(App) export default AppContainer; -```` +``` -# Compatability +# Compatibility For React Native >=0.60.0 use this package For React Native <0.60.0 use [react-native-meteor](https://github.com/inProgress-team/react-native-meteor). diff --git a/docs/api.md b/docs/api.md index 1ae007f..ad97a22 100644 --- a/docs/api.md +++ b/docs/api.md @@ -16,12 +16,15 @@ export default withTracker(() => { ```` ## Meteor -`import { Meteor } from 'meteor-react-native` +`import Meteor from 'meteor-react-native` #### `Meteor.connect(url, options)` Connect to the Meteor Server **options**: +* v2.1.0 BREAKING: AsyncStorage **object** [No default]. You must import and set to your preferred AsyncStorage. Tested libraries: + - `{ AsyncStorage } from 'react-native'` (preferred if using Expo), + - `{ AsyncStorage } from '@react-native-community/async-storage'` * autoConnect **boolean** [true] whether to establish the connection to the server upon instantiation. When false, one can manually establish the connection with the Meteor.ddp.connect method. * autoReconnect **boolean** [true] whether to try to reconnect to the server when the socket connection closes, unless the closing was initiated by a call to the disconnect method. * reconnectInterval **number** [10000] the interval in ms between reconnection attempts. diff --git a/package.json b/package.json index 496dc26..2dada89 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ }, "homepage": "https://github.com/TheRealNate/react-native-meteor#readme", "dependencies": { + "@babel/runtime": "^7.9.6", "base-64": "^0.1.0", "crypto-js": "^3.1.6", "ejson": "^2.1.2", @@ -44,7 +45,7 @@ }, "peerDependencies": { "react": "*", - "@react-native-community/netinfo":"*", + "@react-native-community/netinfo": "*", "@react-native-community/async-storage": ">=1.8.1", "react-native": ">= 0.60.0" } diff --git a/src/Meteor.js b/src/Meteor.js index dc655fb..c4bb165 100644 --- a/src/Meteor.js +++ b/src/Meteor.js @@ -1,4 +1,3 @@ -import { Platform, View } from 'react-native'; import NetInfo from "@react-native-community/netinfo"; import Trackr from 'trackr'; @@ -64,6 +63,10 @@ module.exports = { if (!endpoint) endpoint = Data._endpoint; if (!options) options = Data._options; + if (!options.AsyncStorage) { + console.error('No AsyncStorage solution. Import an AsyncStorage package and add to options in connect() method', e); + } + Data._endpoint = endpoint; Data._options = options; diff --git a/src/user/User.js b/src/user/User.js index 44d8788..c9fb1b1 100644 --- a/src/user/User.js +++ b/src/user/User.js @@ -1,4 +1,4 @@ -import AsyncStorage from '@react-native-community/async-storage'; +// import AsyncStorage from '@react-native-community/async-storage'; import Data from '../Data'; import { hashPassword } from '../../lib/utils'; @@ -34,7 +34,7 @@ module.exports = { }); }, handleLogout() { - AsyncStorage.removeItem(TOKEN_KEY); + Data._options.AsyncStorage.removeItem(TOKEN_KEY); Data._tokenIdSaved = null; this._userIdSaved = null; }, @@ -57,7 +57,7 @@ module.exports = { this._handleLoginCallback(err, result); typeof callback == 'function' && callback(err); - } + }, ); }, logoutOtherClients(callback = () => {}) { @@ -92,7 +92,7 @@ module.exports = { _handleLoginCallback(err, result) { if (!err) { //save user id and token - AsyncStorage.setItem(TOKEN_KEY, result.token); + Data._options.AsyncStorage.setItem(TOKEN_KEY, result.token); Data._tokenIdSaved = result.token; this._userIdSaved = result.id; Data.notify('onLogin'); @@ -120,11 +120,14 @@ module.exports = { async _loadInitialUser() { var value = null; try { - value = await AsyncStorage.getItem(TOKEN_KEY); + value = await Data._options.AsyncStorage.getItem(TOKEN_KEY); } catch (error) { console.warn('AsyncStorage error: ' + error.message); } finally { this._loginWithToken(value); } }, + setItem(){ + + } }; From b1000c2504ad1dc2416f9a2c715809a57d2faf90 Mon Sep 17 00:00:00 2001 From: John Peterson Date: Mon, 11 May 2020 09:44:38 -0700 Subject: [PATCH 02/11] Allows for option to specify AsyncStorage package... Either React Native Async Storage (Expo), with fallback using @react-native-community/async-storage if no AsyncStorage is provided for backwards compatibility. --- README.md | 7 +++---- docs/api.md | 10 +++++----- package.json | 7 +++++-- src/Meteor.js | 10 +++++++++- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index f7a407a..2c524b8 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,10 @@ Connect React Native to your Meteor app. Based on [react-native-meteor](https:// 1. `npm install --save meteor-react-native` 2. Confirm you have peer dependencies installed (`@react-native-community/netinfo`) 3. An AsyncStorage library that you pass to `options` - - `import AsyncStorage from '@react-native-community/async-storage'` OR + - `import { AsyncStorage } from '@react-native-community/async-storage'` OR - @react-native-community/async-storage@>=1.8.1 - - `import AsyncStorage from 'react-native'` - - If using Expo, or cannot otherwise use @react-native-community/async-storage + - `import { AsyncStorage } from 'react-native'` + - If using Expo, or cannot otherwise use `@react-native-community/async-storage` # Basic Usage @@ -18,7 +18,6 @@ Connect React Native to your Meteor app. Based on [react-native-meteor](https:// import Meteor, { Mongo, withTracker } from 'meteor-react-native'; import { AsyncStorage } from 'react-native'; // OR '@react-native-community/async-storage' - let MyCol = new Mongo.Collection("mycol"); Meteor.connect("wss://myapp.meteor.com", { AsyncStorage }); diff --git a/docs/api.md b/docs/api.md index ad97a22..92e000d 100644 --- a/docs/api.md +++ b/docs/api.md @@ -3,7 +3,7 @@ The `withTracker` component is used the same way as [`meteor/react-meteor-data`](https://guide.meteor.com/react.html#using-withTracker) -```` +```javascript export default withTracker(() => { let handle = Meteor.subscribe("mySubscription"); let loading = !handle.ready(); @@ -13,7 +13,7 @@ export default withTracker(() => { myStuff }; })(MyComponent); -```` +``` ## Meteor `import Meteor from 'meteor-react-native` @@ -22,9 +22,9 @@ export default withTracker(() => { Connect to the Meteor Server **options**: -* v2.1.0 BREAKING: AsyncStorage **object** [No default]. You must import and set to your preferred AsyncStorage. Tested libraries: - - `{ AsyncStorage } from 'react-native'` (preferred if using Expo), - - `{ AsyncStorage } from '@react-native-community/async-storage'` +* BREAKING: AsyncStorage **object** [No default]. You must import and set to your preferred AsyncStorage. Tested libraries (must have one installed as dependency): + - `{ AsyncStorage } from 'react-native'` (preferred if using Expo), OR + - `{ AsyncStorage } from '@react-native-community/async-storage'` (defaulted fallback) * autoConnect **boolean** [true] whether to establish the connection to the server upon instantiation. When false, one can manually establish the connection with the Meteor.ddp.connect method. * autoReconnect **boolean** [true] whether to try to reconnect to the server when the socket connection closes, unless the closing was initiated by a call to the disconnect method. * reconnectInterval **number** [10000] the interval in ms between reconnection attempts. diff --git a/package.json b/package.json index 2dada89..62a633d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "meteor-react-native", - "version": "2.0.1", + "version": "2.1.1", "description": "Full Meteor Client for React Native", "main": "src/Meteor.js", "repository": { @@ -27,6 +27,7 @@ "crypto-js": "^3.1.6", "ejson": "^2.1.2", "minimongo-cache": "0.0.48", + "node-require-fallback": "^1.0.0", "prop-types": "^15.5.10", "trackr": "^2.0.2", "underscore": "^1.8.3", @@ -43,10 +44,12 @@ "prettier": "1.12.1", "sinon": "^1.17.3" }, + "optionalDependencies": { + "@react-native-community/async-storage": ">=1.8.1" + }, "peerDependencies": { "react": "*", "@react-native-community/netinfo": "*", - "@react-native-community/async-storage": ">=1.8.1", "react-native": ">= 0.60.0" } } diff --git a/src/Meteor.js b/src/Meteor.js index c4bb165..b94f948 100644 --- a/src/Meteor.js +++ b/src/Meteor.js @@ -64,7 +64,15 @@ module.exports = { if (!options) options = Data._options; if (!options.AsyncStorage) { - console.error('No AsyncStorage solution. Import an AsyncStorage package and add to options in connect() method', e); + const requireIfExists = require('node-require-fallback'); + // Try falling back on current AsyncStorage package. Returns null if not installed. + const { AsyncStorage } = requireIfExists('@react-native-community/async-storage'); + + if (AsyncStorage) { + options.AsyncStorage = AsyncStorage; + } else { + console.error('No AsyncStorage solution. Import an AsyncStorage package and add to `options` in connect() method', e); + } } Data._endpoint = endpoint; From 32585a80d25313b65c0cded08e88c5a29ecd3403 Mon Sep 17 00:00:00 2001 From: John Peterson Date: Mon, 11 May 2020 10:17:34 -0700 Subject: [PATCH 03/11] Remove commented code --- src/user/User.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/user/User.js b/src/user/User.js index c9fb1b1..fd61965 100644 --- a/src/user/User.js +++ b/src/user/User.js @@ -1,5 +1,3 @@ -// import AsyncStorage from '@react-native-community/async-storage'; - import Data from '../Data'; import { hashPassword } from '../../lib/utils'; import call from '../Call'; From 06876fe2d8b472e008f210c10c4f7583c80d47d3 Mon Sep 17 00:00:00 2001 From: John Peterson Date: Mon, 11 May 2020 10:29:07 -0700 Subject: [PATCH 04/11] Fix package version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 62a633d..391dd9a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "meteor-react-native", - "version": "2.1.1", + "version": "2.1.0", "description": "Full Meteor Client for React Native", "main": "src/Meteor.js", "repository": { From a568ded09e69678c464cf3945d117d4c7dcf9af4 Mon Sep 17 00:00:00 2001 From: Nathaniel Dsouza Date: Mon, 11 May 2020 14:18:11 -0400 Subject: [PATCH 05/11] Add "Custom Storage Adapter" to Installation --- README.md | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 2c524b8..1cc2b78 100644 --- a/README.md +++ b/README.md @@ -5,22 +5,29 @@ Connect React Native to your Meteor app. Based on [react-native-meteor](https:// # Installation 1. `npm install --save meteor-react-native` -2. Confirm you have peer dependencies installed (`@react-native-community/netinfo`) -3. An AsyncStorage library that you pass to `options` - - `import { AsyncStorage } from '@react-native-community/async-storage'` OR - - @react-native-community/async-storage@>=1.8.1 - - `import { AsyncStorage } from 'react-native'` - - If using Expo, or cannot otherwise use `@react-native-community/async-storage` +2. Confirm you have peer dependencty `@react-native-community/netinfo` installed +3. Confirm you have `@react-native-community/async-storage@>=1.8.1` installed. If you are using Expo, or otherwise cannot use `@react-native-community/async-storage`, see *Custom Storage Adapter* below. + + +### Custom Storage Adapter +To use a custom AsyncStorage implementation, pass it as an option in `Meteor.connect`: + +```javascript +import { AsyncStorage } from 'react-native'; + +// ... + +Meteor.connect("wss://myapp.meteor.com", { AsyncStorage }); +``` # Basic Usage ```javascript import Meteor, { Mongo, withTracker } from 'meteor-react-native'; -import { AsyncStorage } from 'react-native'; // OR '@react-native-community/async-storage' let MyCol = new Mongo.Collection("mycol"); -Meteor.connect("wss://myapp.meteor.com", { AsyncStorage }); +Meteor.connect("wss://myapp.meteor.com"); class App extends React.Component { render() { From fb813f0ca934907338e5c6686efcbc59f5889f63 Mon Sep 17 00:00:00 2001 From: Nathaniel Dsouza Date: Mon, 11 May 2020 14:22:24 -0400 Subject: [PATCH 06/11] Update AsyncStorage options --- docs/api.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/api.md b/docs/api.md index 92e000d..02e46a4 100644 --- a/docs/api.md +++ b/docs/api.md @@ -22,12 +22,10 @@ export default withTracker(() => { Connect to the Meteor Server **options**: -* BREAKING: AsyncStorage **object** [No default]. You must import and set to your preferred AsyncStorage. Tested libraries (must have one installed as dependency): - - `{ AsyncStorage } from 'react-native'` (preferred if using Expo), OR - - `{ AsyncStorage } from '@react-native-community/async-storage'` (defaulted fallback) * autoConnect **boolean** [true] whether to establish the connection to the server upon instantiation. When false, one can manually establish the connection with the Meteor.ddp.connect method. * autoReconnect **boolean** [true] whether to try to reconnect to the server when the socket connection closes, unless the closing was initiated by a call to the disconnect method. * reconnectInterval **number** [10000] the interval in ms between reconnection attempts. +* AsyncStorage **object** your preferred AsyncStorage. Defaults to `'@react-native-community/async-storage'` as a peer dependency. You will likely want to use `{ AsyncStorage } from 'react-native'` if using Expo #### `Meteor.disconnect()` Disconnect from the Meteor server From 8fc83dcda04877606593967ccd2cbdff5f527b59 Mon Sep 17 00:00:00 2001 From: Nathaniel Dsouza Date: Mon, 11 May 2020 14:22:59 -0400 Subject: [PATCH 07/11] Bump package version to 2.0.2 since no longer a breaking change --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 391dd9a..dd5408e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "meteor-react-native", - "version": "2.1.0", + "version": "2.0.2", "description": "Full Meteor Client for React Native", "main": "src/Meteor.js", "repository": { From 34dc2b5f22aedc2cc644f2da533079f2fb46432d Mon Sep 17 00:00:00 2001 From: Nathaniel Dsouza Date: Mon, 11 May 2020 14:24:21 -0400 Subject: [PATCH 08/11] Throw an error instead of console error if no AsyncStorage installed --- src/Meteor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Meteor.js b/src/Meteor.js index b94f948..2dec797 100644 --- a/src/Meteor.js +++ b/src/Meteor.js @@ -71,7 +71,7 @@ module.exports = { if (AsyncStorage) { options.AsyncStorage = AsyncStorage; } else { - console.error('No AsyncStorage solution. Import an AsyncStorage package and add to `options` in connect() method', e); + throw new Error('No AsyncStorage detected. Import an AsyncStorage package and add to `options` in the Meteor.connect() method', e); } } From 5a63dbb2512077e15dcbe56da0e45a1d56556267 Mon Sep 17 00:00:00 2001 From: John Peterson Date: Mon, 11 May 2020 11:48:17 -0700 Subject: [PATCH 09/11] Remove dead code `setItem()` --- src/user/User.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/user/User.js b/src/user/User.js index fd61965..f6bdee4 100644 --- a/src/user/User.js +++ b/src/user/User.js @@ -125,7 +125,4 @@ module.exports = { this._loginWithToken(value); } }, - setItem(){ - - } }; From 97e24a748c46b87c171d50a9e6d0f46906959442 Mon Sep 17 00:00:00 2001 From: John Peterson Date: Mon, 11 May 2020 14:44:11 -0700 Subject: [PATCH 10/11] Temporary solution to depreciated componentWillUpdate... Using the [`UNSAFE_componentWillUpdate()`](https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate) version to get throgh React v17. --- src/components/ReactMeteorData.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ReactMeteorData.js b/src/components/ReactMeteorData.js index d352ead..abd68ef 100644 --- a/src/components/ReactMeteorData.js +++ b/src/components/ReactMeteorData.js @@ -16,7 +16,7 @@ const ReactMeteorData = { }); }, - componentWillUpdate(nextProps, nextState) { + UNSAFE_componentWillUpdate(nextProps, nextState) { if (this.startMeteorSubscriptions) { if ( !EJSON.equals(this.state, nextState) || From 67060fd5ca4c36195d4aad6064e59120b2f11541 Mon Sep 17 00:00:00 2001 From: John Peterson Date: Tue, 12 May 2020 13:36:33 -0700 Subject: [PATCH 11/11] Moved code to a constructor to replace componentWillMount()... depreciated code --- src/components/ReactMeteorData.js | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/components/ReactMeteorData.js b/src/components/ReactMeteorData.js index abd68ef..823ac70 100644 --- a/src/components/ReactMeteorData.js +++ b/src/components/ReactMeteorData.js @@ -5,16 +5,6 @@ import Data from '../Data'; import MeteorDataManager from './MeteorDataManager'; const ReactMeteorData = { - componentWillMount() { - Data.waitDdpReady(() => { - if (this.getMeteorData) { - this.data = {}; - this._meteorDataManager = new MeteorDataManager(this); - const newData = this._meteorDataManager.calculateData(); - this._meteorDataManager.updateData(newData); - } - }); - }, UNSAFE_componentWillUpdate(nextProps, nextState) { if (this.startMeteorSubscriptions) { @@ -65,6 +55,7 @@ export { ReactMeteorData }; class ReactComponent extends React.Component {} Object.assign(ReactComponent.prototype, ReactMeteorData); + class ReactPureComponent extends React.PureComponent {} Object.assign(ReactPureComponent.prototype, ReactMeteorData); @@ -81,9 +72,23 @@ export default function connect(options) { const BaseComponent = pure ? ReactPureComponent : ReactComponent; return WrappedComponent => class ReactMeteorDataComponent extends BaseComponent { + constructor(props) { + super(props); + + Data.waitDdpReady(() => { + if (this.getMeteorData) { + this.data = {}; + this._meteorDataManager = new MeteorDataManager(this); + const newData = this._meteorDataManager.calculateData(); + this._meteorDataManager.updateData(newData); + } + }); + } + getMeteorData() { return getMeteorData(this.props); } + render() { return ; }