Giter Site home page Giter Site logo

designmanio / react-native-meteor-offline Goto Github PK

View Code? Open in Web Editor NEW
53.0 53.0 23.0 2.99 MB

Caches react-native-meteor collections for offline access.

License: MIT License

JavaScript 81.61% CSS 0.07% HTML 1.35% Python 3.83% Java 2.87% Objective-C 10.27%

react-native-meteor-offline's People

Contributors

jnurkka avatar juliankingman avatar kolyasya avatar license2e avatar radiegtya avatar timordenewitz avatar you-fail-me avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

react-native-meteor-offline's Issues

'cleared' field ignored in ddp event listeners

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?

some info on current limitations pls

@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?

null is not an object (evaluating 'state.hasOwnProperty')

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:

2017-01-25_0825

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

Crash when subscribing

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

Possible Unhandled Promise Rejection (id: 0): XXXXXXXXX is undefined

Note:

  • XXXXXXXXX is the real id of the current user.
  • The app was already running with a current user before installing the package.

[FIXED]

  • I have uninstalled the app on the simulator.
  • I did a meteor reset on meteor.
  • I quit xcode then recompile the app and reinstalled it.
  • Then I created a whole new user.

Clear all the data in the store

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.

Data Loss after SET_READY

222

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,

'Burn with Fire' is too extreme

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

img_1203

TypeError: undefined is not an object (evaluating '(0, _reactNativeMeteor.getData)().db[collection].remove')

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 } });

User object format persistence

It should be interesting to persist the user object differently.
Now it is persisted like this (with a property named with the userID):

screen shot 2017-02-18 at 21 16 05

Use store until sub is ready

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?

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>
  );
};

offline property of MeteorOffline is always false

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?

How to write record

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

Create user issues

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

Unable to resolve module 'redux-persist' when trying to npm link

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

Slow when the dataset large

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?

Could customised combine reducers be injected to createStore?

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?

Subsciptions keep on reloading

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?

Package not bundling

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

Working example

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 !

undefined is not an object (evaluating 'state[collection][id]')

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]) {

[Error] Expected listener to be a function

My code:

export default createContainer(() => {
    GroundedMeteor.subscribe('links.all', 'links.all.id');

    return {
        links: GroundedMeteor.collection('links', 'links.all').find(),
        status: Meteor.status(),
    };
}, App);

simulator screen shot jun 30 2017 10 29 52 pm

User object is null in offline mode

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'.

Current redux state is not written to disk properly

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:

  1. We have one resource to show which is stored in resources collection
    screen shot 2017-03-30 at 6 25 11 pm

screen shot 2017-03-30 at 6 11 28 pm

  1. After we add one more resource to database and delete it, everything works correctly.
    screen shot 2017-03-30 at 6 13 48 pm

screen shot 2017-03-30 at 6 14 27 pm

  1. But after we refresh the app, current redux state is rehydrated to the state after we added the second resource.
    screen shot 2017-03-30 at 6 18 36 pm
    screen shot 2017-03-30 at 6 19 04 pm

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,

[Realm branch] Improvements

I checked some stuff yesterday, and here are some improvements that can considerably boost the perf (connectMeteorRedux.js):

  1. 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)

  2. line 152 - Prefer for loop with cached length over forEach (jsperf)

length = values.length;
for (i = 0; i < length; i++) {
    sum += values[i];
}
  1. line 182 - Don't use stringify, because this is exactly the behavior of Asynctorage we want to avoid (stringify and parsing data). Reference to the point 1. let the user create his own schema

[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:

Can't get online insert to work

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?

_.clone(state) or _.cloneDeep(state.prop)

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,

How to sync inserts/updates after resuming connection

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 :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.