designmanio / react-native-meteor-offline Goto Github PK
View Code? Open in Web Editor NEWCaches react-native-meteor collections for offline access.
License: MIT License
Caches react-native-meteor collections for offline access.
License: MIT License
connectMeteorRedux.js:154
Need to put a }
at the end of the method
More of a question, than an issue. I've noticed that in ddp event listener, which reacts to the CHANGED
event, only the fields
prop of the event obj is respected. But the CHANGED
event also happens with cleared
property, which is an array of fields of the doc, which were unset, i.e. cleared. No action is taken in response to CHANGED
events with cleared
payload.
Is that on purpose? If yes, why?
@JulianKingman thanks again
about to try this... just wanted to ensure I understood
Note that this currently returns all documents, and find queries won't work. I hope to fix that soon.
Does this mean if you do something like returnCached(Meteor.collection('docs').find({some:value}), MeteorStore, 'docs');
it will be the same as returnCached(Meteor.collection('docs').find({}), MeteorStore, 'docs');
?
Also if you have different subscriptions that subscribe to different sub-sets of data, there just stored in the separate variable, right?
eg Subs 1 returns Collection1.find({status:true})
& Subs 2 returns Collection1.find({somefield:123})
you'll return via multiple returnCached statements?
I think my code already same with example but I am ussing connectMeteor instead createContainer. And it produce above error. Here are my code:
getMeteorData(){
const sub = subscribeCached(MeteorStore, 'account', this.selector(), this.options());
return {
// ready: handle.ready()
}
}
selector(){
const search = this.state.search;
return {
'name': {$regex: search, $options: "i"},
};
}
options(){
return {limit: this.state.limit, sort: {createdAt: -1}};
}
here is the complete error:
edit:
I have tried using createContainer but still same error, so I think thats not the cause
Note:
I am not really good at Redux stuff.
please help
Issue being tracked here: rt2zz/redux-persist#244
I'm getting the following crash as my app is loading:
: Unhandled JS Exception: undefined is not an object (evaluating '_newState2.reactNativeMeteorOfflineRecentlyAdded[collection].push')
It seems like the RECENTLY_ADDED dispatch is coming back before the ADDED callback is sometimes and causing me to crash.
Changing the code from
if (
!getCollection ||
!getCollection[id] ||
!_.isEqual(getCollection[id], fields)
) {
// don't insert if it exists
MeteorStore.dispatch({ type: 'ADDED', collection, id, fields });
}
MeteorStore.dispatch({ type: 'RECENTLY_ADDED', collection, id });
to
if (
!getCollection ||
!getCollection[id] ||
!_.isEqual(getCollection[id], fields)
) {
// don't insert if it exists
MeteorStore.dispatch({ type: 'ADDED', collection, id, fields });
}
else{
MeteorStore.dispatch({ type: 'RECENTLY_ADDED', collection, id });
}
Seems to fix the crash, but I don't really know if thats the right thing to do
Note:
[FIXED]
I use this kind of snippet and it doesn't work:
export createContainer((props) => {
const sub = subscribeCached(MeteorStore, 'example', {user: 'Mikey'});
return {
docs: Meteor.collection('docs').find({}),
};
}, component)
As the cache is still here, a new user can get the existing cached values after the previous user has logged out.
Could you provide a cleanup method ?
Hi,
Thanks for the package, it works perfectly fine.
I'm trying to clear all the data that is stored when the user Logouts using the below:
MeteorStore.dispatch({ type: 'HARDRESET' })
Where MeteorStore is the store, as given in the example.
It removes everything but when I refresh the app all the data is back there in the state, any other way with which we can remove all the data as there is no point in storing the data once the user logouts.
Once again Thank you.
Hi @JulianKingman , we use a combine reducers in the initialisation of store and the user reducer is our customised reducer as shown above. After persist/REHYDRATE and SET_READY actions, I am confused why the userObj stored in state would be lost?
Regards,
Each time we call the collection method, the current contents of the collection will be removed and then refilled based on current subscription, which might be too extreme. In our case, it is good to store all of the documents that have been accessed, not just those from current subscription. So we moved the commented codes below to a new function that is called only internet is reconnected.
collection(collection, subscriptionName) {
// console.log(_.get(this.subscriptions, `${subscriptionName}.ready`), `${subscriptionName}.ready`);
// if (!this.offline && _.get(this.subscriptions, `${subscriptionName}.ready`)) {
// const t = new Date();
// const added = _.sortBy(this.store.getState().reactNativeMeteorOfflineRecentlyAdded[collection]);
// const cached = _.sortBy(_.keys(this.store.getState()[collection]));
// // console.log(`got cached in ${new Date() - t}ms`);
// const removed = _.sortBy(_.difference(cached, added));
// // console.log(`got difference in ${new Date() - t}ms`);
// this.store.dispatch({type: 'REMOVE_AFTER_RECONNECT', collection, removed});
// }
this.collections = _.uniq([...this.collections, collection]);
return Meteor.collection(collection);
}
FYI, @JulianKingman @adamgins
Hi @JulianKingman , this is the last action that modifies the redux state and after that, we have 9 resources stored in state.
But when we shut down the server and then refresh the app, persist/REHYDRATE
only carries 6 of them, as shown below,
Wondering the last redux state should be written to disk in the debounce time?
Or this is caused by redux-persist? Please see:
rt2zz/redux-persist#350
rt2zz/redux-persist#355
Just after a new user is first time connected, and each time he tryes to connect, I have this error in this component using GroundedMeteor
export default createContainer(() => {
const meId = Meteor.userId();
const handleDocs = GroundedMeteor.subscribe('getUsersById', 'users.ById', meId);
const handleUsers = GroundedMeteor.subscribe('usersAll', 'users.all');
const handleCountDocs = Meteor.subscribe('countDocs', meId);
return {
docsReady: handleDocs.ready(),
usersReady: handleUsers.ready(),
docs: handleUsers.ready() && handleDocs.ready() && GroundedMeteor.collection('docs', 'getUsersById').find({}, { sort: { created: -1 } }).map((item) => {
... cut ...
}) || [],
docsCountReady: handleCountDocs.ready(),
docsCount: handleCountDocs.ready() && Meteor.collection('counters-collection').findOne('countDocs').count || 0,
---> fails at this last line (483) setting docs -> inside GroundedMeteor.collection (line 67 of connectMeteorRedux.js
case 'REMOVE_AFTER_RECONNECT':
// todo: check for removed docs
const { removed } = action;
const withoutRemoved = _.omit(
state.reactNativeMeteorOfflineRecentlyAdded,
removed
);
getData().db[collection].remove({ _id: { $in: removed } }); <----- HERE
return {
...state,
reactNativeMeteorOfflineRecentlyAdded: withoutRemoved,
};
with this error message
13:38:26 [exp] TypeError: undefined is not an object (evaluating '(0, _reactNativeMeteor.getData)().db[collection].remove')
This error is located at:
in MeteorDataContainer (at Home.js:137)
in RCTView (at View.js:78)
in View (at KeyboardAvoidingView.js:198)
in KeyboardAvoidingView (at Home.js:134)
in RCTView (at View.js:78)
in View (at Container.js:13)
in Container (at Home.js:131)
in Home (created by Connect(Home))
in Connect(Home) (at SceneView.js:17)
in SceneView (at CardStack.js:466)
in RCTView (at View.js:78)
in View (at createAnimatedComponent.js:147)
in AnimatedComponent (at Card.js:12)
in Card (at PointerEventsContainer.js:39)
in Container (at CardStack.js:498)
in RCTView (at View.js:78)
in View (at CardStack.js:414)
in RCTView (at View.js:78)
in View (at CardStack.js:413)
in CardStack (at CardStackTransitioner.js:67)
in RCTView (at View.js:78)
in View (at Transitioner.js:142)
in Transitioner (at CardStackTransitioner.js:19)
in CardStackTransitioner (at StackNavigator.js:41)
in Unknown (at createNavigator.js:13)
in Navigator (at createNavigationContainer.js:226)
in NavigationContainer (at AppWithNavigationState.js:36)
in App (created by Connect(App))
in Connect(App) (at index.js:121)
in RCTView (at View.js:78)
in View (at AlertProvider.js:25)
in AlertProvider (at index.js:120)
in Provider (at index.js:119)
in AppContainer (at createContainer.js:29)
in MeteorDataContainer (at registerRootComponent.js:35)
in RootErrorBoundary (at registerRootComponent.js:34)
in ExpoRootComponent (at renderApplication.js:35)
in RCTView (at View.js:78)
in View (at AppContainer.js:102)
in RCTView (at View.js:78)
in View (at AppContainer.js:122)
in AppContainer (at renderApplication.js:34)
- node_modules/react-native-meteor-redux/connectMeteorRedux.js:67:31 in meteorReduxReducers
- node_modules/redux/lib/createStore.js:178:36 in dispatch
- node_modules/react-native-meteor-redux/connectMeteorRedux.js:290:26 in collection
* app/components/FameHomeView/FameHomeView.js:483:87 in <unknown>
- node_modules/react-native-meteor/src/components/createContainer.js:26:27 in getMeteorData
- node_modules/react-native-meteor/src/components/Mixin.js:121:19 in <unknown>
- ... 32 more stack frames from framework internals
If I comment the line getData().db[collection].remove({ _id: { $in: removed } }); and replace it by console.log(">>> REMOVE_AFTER_RECONNECT ", collection); and log action in meteorReduxReducers
const meteorReduxReducers = (
state = { reactNativeMeteorOfflineRecentlyAdded: [] },
action
) => {
const { type, collection, id, fields, cleared } = action;
console.log(action);
I have this log
Object {
14:05:59 [exp] "collection": "counters-collection",
14:05:59 [exp] "fields": Object {
14:05:59 [exp] "_id": "countDocs",
14:05:59 [exp] "count": 0,
14:05:59 [exp] },
14:05:59 [exp] "id": "countDocs",
14:05:59 [exp] "type": "ADDED",
14:05:59 [exp] }
14:05:59 [exp] Object {
14:05:59 [exp] "id": "countDocs",
14:05:59 [exp] "type": "RECENTLY_ADDED",
14:05:59 [exp] }
14:05:59 [exp] Object {
14:05:59 [exp] "collection": "docs",
14:05:59 [exp] "removed": Array [],
14:05:59 [exp] "type": "REMOVE_AFTER_RECONNECT",
14:05:59 [exp] }
14:05:59 [exp] >>> REMOVE_AFTER_RECONNECT docs
As countDocs is not manage by GroundedCollection this fails ?
So it's not possible to mix Meteor.collection and GroundedMeteor.collection ?
fixed by checking if db[collection] exists :
if (getData().db[collection]) getData().db[collection].remove({ _id: { $in: removed } });
Thank you for your effort on such important thing for meteor & react-native apps! This project is really cool, but I think it would be really great to have a one more feature - I would like to be able to use the store not only while offline, but while waiting for subscriptions as well (what might take a while if there're lots of docs and the internet connection is lame).
I think this should be a separate method, in addition to subscribeCached
, because there're cases when we would prefer waiting for actual data, because it won't be ok to show the data which might be outdated, and there're other cases where we would prefer showing cached (probably slightly outdated) data, but faster, and updating it as soon as we get the real data.
What do you think about such possibility? Do you agree it would be nice, or maybe there're some major caveats? Do you have any bright ideas, on how could it be implemented? Super curious to hear such.
Can you give me the example of a function component?
I don't use class components.
So what can I do? If I want to use meteor subscribe
I use like that
import React, { useState } from "react";
import { View, Text } from "react-native";
import {
Container,
Header,
Content,
Form,
Item,
Input,
Label,
Button,
Text
} from "native-base";
// meteor
import Meteor, { withTracker, MeteorListView } from "react-native-meteor";
Meteor.connect("ws://192.168.1.100:3000/websocket"); //do this only once
let f = {
name: "Bona",
age: 20
};
export default () => {
const [form, setForm] = useState(f);
function btnRegister() {
let doc = {
name: form.name,
age: Number(form.age)
};
Meteor.call("insertCustomer", doc, (err, result) => {
if (result) {
console.log("inserted", result);
} else {
console.log("err", err);
}
});
}
return (
<Container>
<Header />
<Content>
<Form>
<Item fixedLabel>
<Label>Username</Label>
<Input
value={form.name.toString()}
onChangeText={value => setForm({ ...form, name: value })}
/>
</Item>
<Item fixedLabel last>
<Label>Age</Label>
<Input
keyboardType="number-pad"
value={form.age.toLocaleString()}
onChangeText={value => setForm({ ...form, age: value })}
/>
</Item>
<Item>
<Button onPress={btnRegister}>
<Text>Register</Text>
</Button>
</Item>
</Form>
</Content>
</Container>
);
};
Hi @JulianKingman ,
why would the meteorReduxReducers be nested stored after persist/REHYDRATE? If so, the size of meteorReduxReducers will theoretically be close to infinity if we keep refreshing the app?
Regards,
Hello, thank your work on this package.
I'm trying to set it up, but can't understand how offline property should work.
I disabled connection and opened a page with previously stored offline data.
Here is what I have in console.logs for MeteorOffline object.
I suspect offline property should be true
in this case?
Thank you for the great package. Do you have any sample codes that illustrate the writing of records back to Meteor offline and while online?
thank you
Currently when connectivity is restored, all components depending on the data are removed and restored, causing a flicker. We need to make it a little smarter so that data is merged, not completely replaced.
Hey!
I'm having some issues while using Meteor.Accounts.createUser. I get 403 as server response.
Any idea of how I can solve the issue?
Thanks
I am trying to work on a fork for this repo. I was trying to use npm link
to use it on a project while making the changes on them. I can't seem to make it work and I get error that says redux-persist can not be resolved.
Anybody can help me with this?
Here's the error message:
Unable to resolve module `redux-persist` from `/Users/**/**/**/react-native/react-native/app/index.js`: Module does not exist in the module map
This might be related to https://github.com/facebook/react-native/issues/4968
To resolve try the following:
1. Clear watchman watches: `watchman watch-del-all`.
2. Delete the `node_modules` folder: `rm -rf node_modules && npm install`.
3. Reset packager cache: `rm -fr $TMPDIR/react-*` or `npm start -- --reset-cache`.
RCTFatal
__28-[RCTCxxBridge handleError:]_block_invoke
_dispatch_call_block_and_release
_dispatch_client_callout
_dispatch_main_queue_callback_4CF
__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__
__CFRunLoopRun
CFRunLoopRunSpecific
GSEventRunModal
UIApplicationMain
main
start
Hi there,
Can this package be upgraded to meteorrn/core?
Regards
I have slow experience when using android and force close when using ios (deployed version) when my database collection are relative huge. Is this because AsyncStorage only have 6mb Storage or there are another cause? If it was because AsyncStorage, can u give example or alternative what storage can be used and how to implement it?
Thank you so much for your efforts on this project.
Recently, we are developing a react native app based on this library and wondering if there is a way that we could inject our customised reducers to initMeteorRedux Method or createStore method? Then we could be able to make use of the reducers to dispatch actions as the way we want?
Hello,
for my app, i added the subscription as described in the example. The problem I'm facing though is, that it seems to loose the data and loads it again. Sometimes it happens while i have the app open, sometimes when i leave it and go back to it. I cant really determine when its happening. The backend ist a mongo db.
export default createContainer((props) => {
const
kunde = GroundedMeteor.subscribe('kundesub', 'kunde', Meteor.user()),
ansprechpartner = GroundedMeteor.subscribe('ansprechpartnersub', 'ansprechpartnerAll'),
gespraechsprotokoll = GroundedMeteor.subscribe('gespraechsprotokollsub', 'gespraechsprotokollAll'),
umsatzzahlen = GroundedMeteor.subscribe('umsatzzahlensub', 'umsatzzahlenIOS'),
offenePunkte = GroundedMeteor.subscribe('offenePunktesub', 'offenePunkteAll')
return {
kunde: GroundedMeteor.collection('kunde', 'kundesub').find({})
};
}, Kunden)
Am I doing something wrong?
error: bundling: UnableToResolveError: Unable to resolve module react-native/Libraries/Renderer/shims/ReactNative
from /app/node_modules/react-native-meteor-redux/node_modules/react-native-meteor/src/Data.js
: Module does not exist in the module map or in these directories:
/app/node_modules/react-native-meteor-redux/node_modules/react-native/Libraries/Renderer/shims
, /app/node_modules/react-native/Libraries/Renderer/shims
I have already removed npm cleared cache restarted comp reinstalled etc etc but only this package throws the error
Hi @JulianKingman , would this be the data model of how this library works?
Thanks for this amazing package !
Is there any chance to get a simple example repo to see how it is working ?
Plus, is it working with react-native-meteor authentication (like passing a user object to initialState in redux) ?
Again thanks a lot !
When I run my app on a new device (first run), I had this error at meteorReduxReducers (47)
undefined is not an object (evaluating 'state[collection][id]')
The code is
case 'REMOVED':
if (state[collection][id]) {
const newState = _.clone(state);
delete newState[collection][id];
return newState;
}
// console.error(`Couldn't remove ${id}, not found in ${collection} collection`);
return state;
If state[collection] is null, there is this error, so just check that it is not null before should solve the issue
if (state[collection] && state[collection][id]) {
When offline, the only possibility to get user object is with: MeteorStore.getState().
When trying to reach it like another collection in the properties of a component, it is 'null'.
Hi @JulianKingman , how are you doing? we meet an issue that current redux state cannot properly/correctly be written disk which leads to a wrong rehydration.. The process can be seen as follows:
Is this because redux-persist doesn't write the current redux state to disk properly or we hit command + R which is hot reload and just happen in simulator? Any suggestions, please?
Here is the persistStore configuration:
const persistor = persistStore(MeteorStore, { storage: AsyncStorage, keyPrefix: 'react-native-meteor-redux', debounce: 1000 }, () => { MeteorStore.loaded(); });
Regards,
If i log in then log out while obviously connected to Meteor server, then stop the Meteor server and open the app, the MO.user() still is with the user data.
But i have made a successfull logout so MO.user() should be null, right?
Currently, I don't think they are.
I checked some stuff yesterday, and here are some improvements that can considerably boost the perf (connectMeteorRedux.js):
line 103 - The developer should create his own schema. The package shouldn't create them automatically. (reason: better structure, and possibility to custom property of the Realm object)
line 152 - Prefer for loop with cached length over forEach (jsperf)
length = values.length;
for (i = 0; i < length; i++) {
sum += values[i];
}
[PS]: I know this is a lot of work to do again but I'm pretty sure it is definitely worthy for boosting perf a lot.
some sources:
Hello!
I'm trying to insert a document while online, but i'm having some issues. I can list the #documents of the details collections property.
To insert the document I use
var doc = {name: {first: 'test'}}; Meteor.collection('details').insert(doc);
. Is this correct?
Do I need to add anything to meteor to make this work? Or i'm I doing something wrong?
Thank you for all your help @JulianKingman
I may be wrong, but as far as i know, the previous state is suggested to stay unchanged but _.clone is a shallow copy of the state :
var objects = [{ 'a': 1 }, { 'b': 2 }];
var shallow = _.clone(objects);
console.log(shallow[0] === objects[0]);
// => true
ref: https://lodash.com/docs/4.17.4#clone
So when we are mutating newState
, are we mutating the previous state?
For example, if we are gonna modify the resources property of state, I would suggest:
newState = _.clone(state);
newRes = _.cloneDeep(state.resources);
newState.resources = newRes;
return newState;
which will distinguish the previous state and the new state, and tell the store that the resources property have been changed.
This may also raise the issue of #35 , i.e. persist-redux thinks the state or the property hasn't been changed, so it won't persist the state or the property to disk.
You might be interested in this discussion:
rt2zz/redux-persist#90
regards,
just like in whatsapp,
if we dont have internet access, it will still let us type and when click send it will display message store locally in device abut not sync to server unless device has internet connection back.
i am really new, want to achieve this function.. it is working when internet.. also offline working as well when i quit application and stop internet, still shows old data.. but after that, if i go to chat box and type and press enter, nothing happens.. atleast how to store it in local redux and persist untll internet connection back and start sync :)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.