vasern / vasern

Vasern is a fast, lightweight and open source data storage for React Native

Home Page:https://vasern.github.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

previousCommitedItems.concat is not a function.

0mars opened this issue · comments

Trying to save a document and it ends up like this

Unhandled promise rejection, [TypeError: previousCommitedItems.concat is not a function. (In 'previousCommitedItems.concat(_this8._commitedItems[key])', 'previousCommitedItems.concat' is undefined)]

Here is the code

export class UserProvider {
    private model: Document;

    public constructor() {
        this.model = db.get('User');
        this.model.load();
    }

    public async authorize(user: User): Promise<false | NewObject[]> {
        this.removeAll();
        return this.model.insert(user, true); // <<<<<<<<<<<<<<<< here
    }

    public get(): User {
        if (this.model.count() < 1) {
            throw new UserNotFoundError('User not found!');
        }
        return <User>this.model.data().find(e => true);
    }

    private removeAll() {
        this.model.data().forEach(function (item) {
            db.remove(item, true);
        });
    }

Hi @0mars, turn out recent changes of React Native version 0.60 requires some updates in order to use the library. I'll make an update soon!

@hieunc229 thanks for your response, keep me posted!

@0mars, I have pushed an update. Please update vasern to the latest version, then follow the installation instruction

I have tested on both iOS and Android, please let me know if the issue persists

@hieunc229 wuhoo!! sure will test and get back to you

Thank you @0mars :)

@hieunc229 I'm getting
Console output:
Running application on XXXXX
undefined
undefined
undefined
undefined

I'm using expo, I guess 4 is the number of fields I'm trying to save, the unhandled promise rejection exception doesn't show anything or say anything, any ideas ?

it says the same error again
sorry, now it shows the exception

Unhandled promise rejection, [TypeError: previousCommitedItems.concat is not a function. (In 'previousCommitedItems.concat(_this8._commitedItems[key])', 'previousCommitedItems.concat' is undefined)]

  • node_modules/expo/build/environment/muteWarnings.fx.js:27:24 in error
  • ... 11 more stack frames from framework internals

and FYI, I tried to use AsyncStorage directly, and got the same undefined, but it was more like a loop, it kept printing undefined forever

Oh, I didn't know you were using Expo. Last time I remember, Expo doesn't directly support native modules, which vasern is a native module. If you are just testing, you can try to eject Expo, then reinstall vasern

Secondly, if the error previousCommitedItems.concat is not a function still show up, I guess the library hasn't been updated yet. Sometimes you will need to clear the cache.

To clear cache, run the below command:

  • With Expo exp r -c
  • Without Expo npm start -- --reset-cache

I have tried to use the latest Expo and confirm that native modules are still not supported by Expo. On their documentation, there are 2 options available which are AsyncStorage and SQLite

@hieunc229 thanks, I have a chance to test now, and I am having problems deleting documents, but saving is apparently working properly now

Unhandled promise rejection TypeError: VasernManager.ClearDocument is not a function

private removeAll(): Promise<void> {
        return this.model.removeAllRecords()
    }

Hey @0mars, looks like you are using typescript. The removeAllRecords should work but it's not an "official" feature and does not exist in the type definitions yet.

You might want to ignore the this type error (using // @ts-ignore)

so how to remove all docs from a collection? so // @ts-ignore for remove all records shall solve it ?

Sorry for the confusion, this should ignore the type error.

// @ts-ignore
this.model.removeAllRecords()

P/s: Yes, removeAllRecords should remove all records (or docs) from a collection

thanks, this still didn't work but the following did:

export class UserProvider {
    private model: Document;

    public constructor() {
        this.model = db.get('User');
        this.model.load();
    }

    public async authorize(user: User): Promise<false | NewObject[] | void> {
        this.removeAll();

        return this.model.insert(user, true);
    }

    public get(): User {
        if (this.model.count() < 1) {
            throw new UserNotFoundError('User not found!');
        }
        console.log(this.model.data()); // remark on here
        return <User>this.model.data()[1];
    }

    private removeAll() {
        this.model.data().forEach(function (item) {
            db.remove(item, true);
        });
    }
}

client:

const userData: User = {
            username: "myuser",
            token: "token",
            uuid: "uuid",
            id: "id",
        };
        // console.log(userProvider.get());
        userProvider.authorize(userData).then((data) => {
            console.log(data);
            console.log('authorized');
            setTimeout(() => console.log(userProvider.get()), 1000); // wuthout this, the .get returns empty
        });

// model.data() returns an array first element is an internal object I guess {id: n}

[
  {
    "id": "n"
  },
  {
    "id": "id",
    "username": "myuser",
    "token": "token",
    "uuid": "uuid"
  }
]

Is there a better way of reliably getting the only real record, or maybe by using filters ? the first element is less than ideal to have, having a datastore with just metadata would be more favourable I guess

Hey @0mars, there are 2 things about the insert function

  1. It will return an array of new objects (not promise)
  2. id field will be ignored. If you really need the id field, you might need to use a different name. Otherwise, it will cause unexpected behavior (like creating an extra record in your example)

I made little changes and tested your example.

// UserProvider
export class UserProvider {
    private model: Document;

    public constructor() {
        this.model = db.get('User');
        // 1st updates: remove this.modal.load()
    }

    // 2st updates: remove `async`, return `NewObject`
    public authorize(user: User): false | NewObject[] {
        this.removeAll();

        // 3rd updates: remove `true` since it's true by default
        return this.model.insert(user);
    }

    public get(): User {

        // 4th updates: use `length` instead of `count`
        if (this.model.length() < 1) {
            throw new UserNotFoundError('User not found!');
        }
        console.log(this.model.data()); // remark on here
        // 5th updates: I guess you want to use the first record
        return <User>this.model.data()[0];
    }

    private removeAll() {
        // 6th updates: use shortcut, if it shows `TypeError`, ignore it
        this.model.removeAllRecords()
    }
}
const userData: User = {
    username: "myuser",
    token: "token",
    uuid: "uuid",
    // 7th updates: remove id
    // id: "id", 
};
// 8th updates: use returned data as an object instead of promise
const data = userProvider.authorize(userData);
console.log(data);
console.log('authorized');

Let me know how it goes!

Also, when the app started, it will need a little time to load the data. It's a good practice to get/insert/update after the data is ready.

For example, I added a ready function within UserProvider class

public ready(fn: Function) {
  this.model.onLoaded(fn)
}

Then I can use

userProvider.ready(() => {
  let user = userProvider.get()
})
const userData: User = {
            username: "myuser",
            token: "token",
            uuid: "uuid",
        };
        const data = userProvider.authorize(userData);
        console.log('authorized');
        console.log(data);
        userProvider.whenReady(() => console.log(userProvider.get())); // never gets executed
public get(): User {
        if (this.model.length() < 1) {
            throw new UserNotFoundError('User not found!');
        }
        console.log(this.model.data()); // 13 rows found
        return <User>this.model.data()[0]; {'id': 'n'}
    }

I removed the ID from my data definition, but I guess I have to delete all

this.model.removeAllRecords(); // creashes the app and does nothing
Unhandled promise rejection TypeError: VasernManager.ClearDocument is not a function

and does nothing, still 13 records

nothing deletes the records now :(

Alright, I remember the removeAllRecords isn't an official feature since it was only supported on iOS.

I have just pushed a new update to support the feature on Android as well. Please upgrade to the latest version 0.3.61, reset cache and try again. Let me know if any issue still exists