ngxs-labs / immer-adapter

:hamster: Declarative state mutations
MIT License
46 stars 10 forks source link

Error: TypeError: 'ownKeys' on proxy: trap result did not include 'scope' #162

Open xmlking opened 5 years ago

xmlking commented 5 years ago

after switching to @ngxs-labs/immer-adapter": "^2.0.1", i am getting following error

  @Mutation()
  @Action(CreateNewConversation)
  createConversation(ctx: StateContext<ChatBoxStateModel>) {
    const newConversation = new Conversation('payload.conversationId'); 
    ctx.setState((state: ChatBoxStateModel) => {
      state.conversations.push(newConversation);
      state.activeConversationId = newConversation.id;
      return state;
    });
  }
core.js:5567 ERROR TypeError: 'ownKeys' on proxy: trap result did not include 'scope'
    at Function.freeze (<anonymous>)
    at deepFreeze (ngxs-store.js:1514)
    at ngxs-store.js:1529
    at Array.forEach (<anonymous>)
    at deepFreeze (ngxs-store.js:1519)
    at Object.setState (ngxs-store.js:1607)
    at setStateValue (ngxs-store.js:1728)
    at Object.setState (ngxs-store.js:1785)
    at Object.setState (ngxs-labs-immer-adapter.js:82)
    at ChatBoxState.push.../../libs/chat-box/src/lib/state/chat-box.store.ts.ChatBoxState.createConversation (chat-box.store.ts:192)
splincode commented 5 years ago

You need disabled development mode

splincode commented 5 years ago

However, this is a bug and I need to reproduce it.

xmlking commented 5 years ago

Here is my project when you can reproduce https://github.com/xmlking/ngx-starter-kit/blob/develop/libs/chat-box/src/lib/state/chat-box.store.ts

splincode commented 5 years ago

@xmlking well I was able to reproduce the error

image

splincode commented 5 years ago

Fixed

image

xmlking commented 5 years ago

I cannot import import { ImmutableContext, ImmutableSelector } from '@ngxs-labs/immer-adapter'; some how they are missing in published v3.0.0 npm module!

image

splincode commented 5 years ago

Sorry

splincode commented 5 years ago

done (v3.0.1)

xmlking commented 5 years ago

No problem. appreciate your work and quick release 👍

victos commented 5 years ago

Again

ERROR TypeError: 'ownKeys' on proxy: trap result did not include 'scope' at Function.freeze () at deepFreeze (ngxs-store.js:1420) at ngxs-store.js:1435 at Array.forEach () at deepFreeze (ngxs-store.js:1425) at ngxs-store.js:1435 at Array.forEach () at deepFreeze (ngxs-store.js:1425) at Object.setState (ngxs-store.js:1649) at setStateValue (ngxs-store.js:1770)

splincode commented 5 years ago

@victos create issue with reproduce

victos commented 5 years ago

This error occurred when I get the property from getState and put it back within setState. Maybe this is not a bug. The property get from the getState is not a pure JavaScript object.

splincode commented 5 years ago

I will not be able to help unless I see specific examples.

victos commented 5 years ago

Here's an example, https://stackblitz.com/edit/angular-jwqaif3?file=src/app/app.module.ts

dfa1234 commented 5 years ago

Sorry to emphase but It's a catastrophic bug. I'm losing a lot of time to make a workaround for this. Any advise would be welcome, thank.

victos commented 5 years ago

Sorry to emphase but It's a catastrophic bug. I'm losing a lot of time to make a workaround for this. Any advise would be welcome, thank.

Maybe you can use the function isDraft to know if an object is a Proxy, and use function original to get the pure JavaScript object from the Proxy Here’s the doc of immer: https://github.com/immerjs/immer#extracting-the-original-object-from-a-proxied-instance

dfa1234 commented 5 years ago

Thank. I learned I need to learn more about Proxy :)

Anyway I finally found a workaround, before reading you comment. I presume original from immer is better than my solution, which is simply to make a deep clone (using JSON parse/ stringify)

  @Action(OpenCategory)
  @ImmutableContext()
  openCategory({setState, getState}: StateContext<CatalogState>, {categoryToOpen}: OpenCategory) {

    let state: CatalogState = cloneDeep(getState());

    state.current.page = 0;
    state.current.product = null;

   // until now, we are cool.`setState` would work:
   // setState(s => state);

   // But now this line would error my setState:
   // state.current.category = categoryToOpen;

   // `categoryToOpen` is indeed a proxy
   // So I simply had to make a clone to make is work (cloneDeep is just a JSON parse /stringify)
    state.current.category = cloneDeep(categoryToOpen);

   // Edit: just tested and indeed, using original work like  charm
   state.current.category = original(categoryToOpen);

   //working
   setState(s => state);

}

Any comment on the above code is more than welcome

xtreemrage commented 4 years ago

@dfa1234 I would not use JSON serialization if you have a complex object with functions etc. You you can loose properties, like Function and Infinity and you will also lose properties with undefined values.

Only use it if you have a simple object with only values.