Replies: 5 comments 1 reply
-
I'm not super familiar with the behavior/usage of devtools. @Aslemammad can you help us? |
Beta Was this translation helpful? Give feedback.
-
What we send to devtools ext and what we receive from it is not identical. We don't have such actions unless with redux middleware. The code we receive action and restore the state is added recently. #608 |
Beta Was this translation helpful? Give feedback.
-
Okay so let me give a little background, the main interactions with the devtools are:
For For For (note that this whole thing works a little differently when we also have a redux middleware but that's not relevant for now) Now the if (message.type === 'ACTION' && message.payload) {
try {
api.setState(JSON.parse(message.payload))
} catch (e) {
console.error(
'please dispatch a serializable value that JSON.parse() support\n',
e
)
} And why did it add it? As the PR says it was inspired by pmndrs/valtio#261 which added a similar piece of code... if (message.type === 'ACTION' && message.payload) {
try {
Object.assign(proxyObject, JSON.parse(message.payload))
} catch (e) {
console.error(
'please dispatch a serializable value that JSON.parse() and proxy() support\n',
e
)
}
} But here is the difference between zustand and valtio, in zustand we send names as actions but in valtio we send state change as the action: const unsub1 = subscribe(proxyObject, (ops) => {
const action = ops
.filter(([_, path]) => path[0] !== DEVTOOLS)
.map(([op, path]) => `${op}:${path.map(String).join('.')}`)
.join(', ')
if (!action) {
return
}
if (isTimeTraveling) {
isTimeTraveling = false
} else {
const snapWithoutDevtools = Object.assign({}, snapshot(proxyObject))
delete (snapWithoutDevtools as any)[DEVTOOLS]
devtools.send(
{
type: action,
updatedAt: new Date().toLocaleString(),
},
snapWithoutDevtools
)
}
}) So pmndrs/valtio#261 was correct because valtio sends state as action but #608 was incorrect because zustand sends "names" as action.
Yes but in some cases it's identical and in the cases it's not I 90% know how the devtools work and how are we supposed to interact with it and what the behavior should be, hence in #662 I ignored the current behavior and code and did a "rewrite" instead of a "refactor". Now we have two options:
I'd suggest we go with Also If I'm rewriting and you want me to it in a separate PR, I'd preferably want to base it on #662 because I'm very particular with types. For example when we're updating state from devtools, we do it "silently" and I have typed things in a way that if we accidently do (I'll also document a bit of "the correct way" to types in #662 at the end) |
Beta Was this translation helpful? Give feedback.
-
Is this currently implemented? Or, you would do so?
It's state itself, not state change. But, I guess you understand it correctly. Overall, your suggestion sounds valid and better. My only request is to do this improvement&fix before v4, meaning before #662. (even if the typing is not precise.)
That would be really nice. |
Beta Was this translation helpful? Give feedback.
-
It is currently implemented. You can see it here, first we assign zustand/src/middleware/devtools.ts Line 128 in 833f57e ...then we api.setState it...zustand/src/middleware/devtools.ts Line 133 in 833f57e
No I meant the const action = ops
.filter(([_, path]) => path[0] !== DEVTOOLS)
.map(([op, path]) => `${op}:${path.map(String).join('.')}`)
.join(', ')
Thanks for considering it!
Okay I'll give it a try. |
Beta Was this translation helpful? Give feedback.
-
(For #662) I don't fully understand the code nor I fully understand how the redux devtools work, my understanding is mostly based on this and this, so I have some questions.
If I understand correctly the message of type
{ type: "ACTION", payload }
would have the action as the payload and not the state but yet we're setting it as the state viasetState(JSON.parse(message.payload))
:zustand/src/middleware/devtools.ts
Line 116 in 833f57e
@dai-shi speculated that we might be sending the state as action object. But that's not the case, you send the action to devtools via
send
method that is of signature(action, state) => void
, in all 3 references ofdevtools.send
...zustand/src/middleware/devtools.ts
Line 86 in 833f57e
zustand/src/middleware/devtools.ts
Line 106 in 833f57e
zustand/src/middleware/redux.ts
Line 32 in 833f57e
...we're always send a string as an action and not state. So that'd make the following...
zustand/src/middleware/devtools.ts
Line 116 in 833f57e
...a bug, right? Am I missing something?
Why are we deleting
api.devtools
when we haven't even setted it yet? No other middleware sets it, and nor any other middleware should be allowed to set it afaiu.zustand/src/middleware/devtools.ts
Line 80 in 833f57e
Similarly why are we making this
!api.devtools
check here? Wouldn'tapi.devtools
always beundefined
here?zustand/src/middleware/devtools.ts
Line 91 in 833f57e
Also
devtools
should overwritesetState
to benamedSetState
(ie the third argument acts like a name/action for the state update) which we do here...zustand/src/middleware/devtools.ts
Line 89 in 833f57e
But the we overwrite
namedSetState
if!api.devtools
(which always will betrue
afaict) here... and now we don't care about the third parameter, why so?zustand/src/middleware/devtools.ts
Lines 93 to 109 in 833f57e
Okay ffs I realised we are calling the
savedSetState
(which will benamedSetState
?) but then we don't pass the third parameter...?zustand/src/middleware/devtools.ts
Line 104 in 833f57e
Let me ask these questions for now. Either the code is weird or I'm being dumb and missing a major piece.
I can leave the devtools (and redux) middleware as it is but it's important to understand the runtime behavior to type things, without that I can't do much. Not to mention it'll be odd if all other pieces of codebase get polished and this remains less accessible.
Beta Was this translation helpful? Give feedback.
All reactions