Nozbe / WatermelonDB

🍉 Reactive & asynchronous database for powerful React and React Native apps ⚡️
https://watermelondb.dev
MIT License
10.62k stars 600 forks source link

Confused with using action and subAction #468

Closed jembach closed 5 years ago

jembach commented 5 years ago

Hi,

I'm confused with using the action and subAction. Sometimes it works and sometimes not.

For example this batch delete does not work: await database.action(action => action.subAction(() => database.batch(allRecords))); It will throw every time the error: Unhandled Promise Rejection: Diagnostic error: Database.batch() can only be called from inside of an Action. See docs for more details.

Also this piece of code doesn't work: await database.action(action => action.subAction(() => currentUser.addChats(result))); Running it the first time it will crash. But when it runs seconds, it runs. but I don't know why.

Can anyone give me a good example and explanation, how to run actions correctly.

rkrajewski commented 5 years ago

Hi @jembach,

Not sure what currentUser.addChats does, but at first look, it seems the subAction callbacks don't return an action.

const subAction = () => database.action(() => {
  database.batch(allRecords)
})

await database.action(action => action.subAction(subAction))

docs -> https://nozbe.github.io/WatermelonDB/Actions.html?highlight=subAction#calling-actions-from-actions

jembach commented 5 years ago

Hi @rkrajewski,

the currentUser.addChats contains the following code:


    for (let i = 0; i < chats.length; i += 1) {
      const chat = chats[i];
      let [chatLocal] = await this.chats.extend(Q.where('remote_id', chat.id)).fetch();

      if (!chatLocal) {
        chatLocal = await chatsCollection.create(newChat => {
          newChat.remoteId = chat.id;
          newChat.name = chat.name;
          newChat.type = chat.type;
          newChat.role = chat.role;
          newChat.invited_at = chat.invitedAt;
          newChat.created_at = chat.createdAt;
          newChat.account.set(this);
        });
        await this.subAction(() => chatLocal.setAvatar(chat.avatar));
      } else {
        await this.subAction(() => chatLocal.setAvatar(chat.avatar));
      }
    }

Not sure what currentUser.addChats does, but at first look, it seems the subAction callbacks don't return an action.

I doesn't know, that it has to return an action. Does this code returns an action? I'm not sure

rkrajewski commented 5 years ago

I assume currentUser is a model, so you can simply decorate addChats method with @action decorator.


class CurrentUser extends Model {
  /* ... class definition */

  @action addChats() {
     // your code goes here
  }
}
jembach commented 5 years ago

Yes of course. I have also done this. Nevertheless the error occures.

rkrajewski commented 5 years ago

And how about setAvatar - is it an @action as well? Besides, I'm sure what does the code of setAvatar do. Does it work if chatLocal has been found, or doesn't for both cases? Can you provide more specific example of your code?