Immer: How to log modified draft state?

Created on 30 Apr 2020  ยท  12Comments  ยท  Source: immerjs/immer

๐Ÿ™‹โ€โ™‚ Question

I want to log a complex draft modification (for debug, in react-app-rewired script).

Given e.g.:
```js
module.exports = (config, env) => immer.produce(config, draft => {
draft.foo.bar = baz;
call.some.mutating.function(draft);

console.log(immer.original(draft)); // this I can do
console.log(immer.resulting(draft)); // this I cannot do
});

I know I can log the draft itself, but it's pretty messy and seemingly unusable for deeply nested data.

question

Most helpful comment

With Immer 7, it will be possible to call console.log(current(draft)) which will be a lot more efficient than stringifying.

All 12 comments

you can try console.log(JSON.stringify(draft, null, 2))

On Thu, Apr 30, 2020 at 8:54 AM Dima Tisnek notifications@github.com
wrote:

๐Ÿ™‹โ€โ™‚ Question

I want to log a complex draft modification (for debug, in
react-app-rewired script).

Given e.g.:

module.exports = (config, env) => immer.produce(config, draft => {

draft.foo.bar = baz;

call.some.mutating.function(draft);

console.log(immer.original(draft)); // this I can do

console.log(immer.resulting(draft)); // this I cannot do

});

I know I can log the draft itself, but it's pretty messy and seemingly unusable for deeply nested data.

โ€”
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/immerjs/immer/issues/591, or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAN4NBER3ONKY2HIXQFBCVTRPEVFHANCNFSM4MVITWGA
.

Yes that works, thank you!
And thus, I guess I can always do JSON.parse(JSON.stringify(draft)) to get a PDO :)

Correct, nonetheless I like your API proposal, feel free to leave this
issue open :)

On Thu, Apr 30, 2020 at 10:32 AM Dima Tisnek notifications@github.com
wrote:

Yes that works, thank you!
And thus, I guess I can always do JSON.parse(JSON.stringify(draft)) to
get a PDO :)

โ€”
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/immerjs/immer/issues/591#issuecomment-621722731, or
unsubscribe
https://github.com/notifications/unsubscribe-auth/AAN4NBGWI7O2NOWUFC2PWM3RPFARDANCNFSM4MVITWGA
.

Weirdly, the JSON.stringify hack (over webpack config) doesn't work with CRA yarn start...
My setup is CRA + react-app-rewired + my custom config-overrides.js.
Specifically, just adding void(JSON.stringify(draft)); where draft is webpack config, like {mode: "development", plugins: ...} makes yarn start fail with:

Failed to compile.

Cannot add property hidePathInfo, object is not extensible

error Command failed with exit code 1.

I wonder if applying JSON to the draft somehow changes the draft internally. ๐Ÿค”

Wow that is weird. As a quick fix try disable autoFreeze?

On Fri, 1 May 2020, 08:34 Dima Tisnek, notifications@github.com wrote:

Weirdly, the JSON.stringify hack (over webpack config) doesn't work with
CRA yarn start...
My setup is CRA + react-app-rewired + my custom config-overrides.js.
Specifically, just adding void(JSON.stringify(draft)); where draft is
webpack config, like {mode: "development", plugins: ...} makes yarn start
fail with:

Failed to compile.

Cannot add property hidePathInfo, object is not extensible

error Command failed with exit code 1.

I wonder if applying JSON to the draft somehow changes the draft
internally. ๐Ÿค”

โ€”
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/immerjs/immer/issues/591#issuecomment-622284441, or
unsubscribe
https://github.com/notifications/unsubscribe-auth/AAN4NBD7WRHAZR3KWL6NLVLRPJ3PXANCNFSM4MVITWGA
.

Yes, immer.setAutoFreeze(false) at module top level, before the invocation of immer.produce solve this!

On a related note, I think I've found a case where it would be nice, though not strictly required to have live access to modified state.

I'd like to be able to write something like this:

case "SET_SEARCH":
  draft.search_terms = action.search;
  draft.search_hits = search(draft.data, draft.search_index, draft.search_terms);
case "SET_DATA":
  draft.data = action.data;
  draft.search_hits = search(draft.data, draft.search_index, draft.search_terms);
case "SET_INDEX":
  draft.search_index = action.index;
  draft.search_hits = search(draft.data, draft.search_index, draft.search_terms);

However, that fails because search is dumb and cannot handle Proxy objects.

So, for now I have to write

case "SET_SEARCH":
  draft.search_terms = action.search;
  draft.search_hits = search(original(draft.data), original(draft.search_index), action.search);
case "SET_DATA":
  draft.data = action.data;
  draft.search_hits = search(action.data, original(draft.search_index), original(draft.search_terms));
case "SET_INDEX":
  draft.search_index = action.index;
  draft.search_hits = search(original(draft.data), action.index, original(draft.search_terms));

Which is explicit ๐Ÿ‘but wonky and search calls don't look the same ๐Ÿ‘Ž

P.S. I don't want to use JSON.parse(JSON.stringify(draft.data)) because data is quite large.

can you clarify why search doesn't work with proxies? proxies are
undetectable in javascript, so the fact that a draft is a proxy should in
itself not matter.

On Mon, May 18, 2020 at 9:23 AM Dima Tisnek notifications@github.com
wrote:

On a related note, I think I've found a case where it would be nice,
though not strictly required to have live access to modified state.

I'd like to be able to write something like this:

case "SET_SEARCH":

draft.search_terms = action.search;

draft.search_hits = search(draft.data, draft.search_index, draft.search_terms);
case "SET_DATA":

draft.data = action.data;

draft.search_hits = search(draft.data, draft.search_index, draft.search_terms);
case "SET_INDEX":

draft.search_index = action.index;

draft.search_hits = search(draft.data, draft.search_index, draft.search_terms);

However, that fails because search is dumb and cannot handle Proxy
objects.

So, for now I have to write

case "SET_SEARCH":

draft.search_terms = action.search;

draft.search_hits = search(original(draft.data), original(draft.search_index), action.search);
case "SET_DATA":

draft.data = action.data;

draft.search_hits = search(action.data, original(draft.search_index), original(draft.search_terms));
case "SET_INDEX":

draft.search_index = action.index;

draft.search_hits = search(original(draft.data), action.index, original(draft.search_terms));

Which is explicit ๐Ÿ‘but wonky and search calls don't look the same ๐Ÿ‘Ž

โ€”
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/immerjs/immer/issues/591#issuecomment-630025269, or
unsubscribe
https://github.com/notifications/unsubscribe-auth/AAN4NBBPQR545P2ARFFWW5LRSDV63ANCNFSM4MVITWGA
.

I can't reproduce the proxy making a difference any more ๐Ÿค”
Perhaps I had some other bug at the time...

When I'm comparing calling my search with and without original(...), all I can see is:

  • passing draft is at least 2x slower than original(draft) over any data I try
  • sometimes, passing draft is 16x slower than original(draft)

I'm testing this with a data set of 4K objects, each having ~4 searchable fields, and in practice the performance is pretty good with or without original. I ought to support 100K objects though, so I'm trying to be proactive.

That is correct, drafts are much slower to operate on, especially if you
read a ton. Since search is not a mutating operation, there is no need at
all to do that in a produce. I'd search first, then do the update after
that in a produce

On Tue, 19 May 2020, 06:19 Dima Tisnek, notifications@github.com wrote:

I can't reproduce the proxy making a difference any more ๐Ÿค”
Perhaps I had some other bug at the time...

When I'm comparing calling my search with and without original(...), all
I can see is:

  • passing draft is at least 2x slower than original(draft) over data I
    try
  • sometimes, passing draft is 16x slower than original(draft)

I'm testing this with a data set of 4K objects, each having ~4 searchable
fields, and in practice the performance is pretty good with or without
original. I ought to support 100K objects though, so I'm trying to be
proactive.

โ€”
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/immerjs/immer/issues/591#issuecomment-630586462, or
unsubscribe
https://github.com/notifications/unsubscribe-auth/AAN4NBGZOSDMNGSXRSZHJBLRSIJGBANCNFSM4MVITWGA
.

With Immer 7, it will be possible to call console.log(current(draft)) which will be a lot more efficient than stringifying.

Was this page helpful?
0 / 5 - 0 ratings