You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Note:
It seems `done` on line 82 is executed once (log on line 88), but the callback
of `setMsgs` is executed multiple times (log on line 92). It is expected to
execute only once, or line 56 would fail because `custom` is already parsed.
More strangely, uncommenting `try-catch` on line 54,57-59 seems to change this
multi-execute behavior/bug mysteriously. `catch` seems never executed (log on
line 58) and `setMsgs` callback seems only executes once (log on line 92).
Theorically it should be related to inplace mutation of `obj.msgs`/`msg.custom`,
but the behavior above looks more like a React codegen issue. Tracing up to the
multi-execute of callback is hard.
However, with `console.trace` or `obj.debug` (a mutating counter), or with
`debugger` or breakpoint, we can see that it actually execute 3 times without
`try-catch` and 2 times with it, (rather than 2 vs 1). For some reason
`console.log` does not work on the 2nd execution (1st and 3rd ok) but
`console.trace` works all the time. Similarly, the `catch` on line 58 is
executed but its `console.log` is muted because it is during 2nd run.
This makes a little bit more sense. With `try-catch`, the 2nd execution is no-op
and nothing gets mutated. So it works as expected. Without it, the 2nd execution
throws and somehow React decides to run it 3rd time, which finally make React
unhappy.
It is left unknown why `console.log` is less useful than `console.trace`. And
whether/how React's multi-execution of callback is related to mutation of object
captured by the closure. But anyways, the action should be a descriptive object
and reducer should be pure (or at least idempotent here).
React.StrictMode calls the callback twice intentionally.
facebook/react#12856 (comment)
Note that parsing and reversing was outside `setMsgs` in `HEAD^`, so it executes
only once as expected. For performance, we may extract sanitization unrelated to
`msgsPrev` (eg. !resend and parsing) outside of `setMsgs`.
`console.log` was overwritten as `function disabledLog() {}` by React during the
2nd call to hide its side effects.
0 commit comments