Q: In useState example `Hooks.get stateToken` is not really necessary right?
safareli opened this issue · 2 comments
In useState example Hooks.get stateToken
is not really necessary right?
I think like that because if state changes this component will re-render and therefore that div
will have new onClick
listener referencing to new update
which references new state
and one can just reference state there instead of using Hooks.get stateToken
. Is my reasoning right here? I.e. It's like that because it's sort of best practice right?
If yes, then adding something like this:
(In this particular example using
state
instead ofHooks.get stateToken
would work correctly)
In Note:
section might be useful
That's correct, it isn't always necessary to call Hooks.get
to get the current state within effectful code. You only need to make sure to retrieve the latest value of state if it is possible that your effectful function will be called in a different context than the one it was defined in.
So as you explained, it's not necessary to call Hooks.get
within update
in this code, because the value it returns is going to be the same as state
.
Hooks.do
state /\ stateToken <- Hooks.useState initialState
intState /\ intStateToken <- Hooks.useState 0
let
update :: HookM _ _ _ Unit
update = do
-- Get the current value of the first state
currentState <- Hooks.get stateToken
-- ...
Hooks.useLifecycleEffect do
Hooks.modify_ intStateToken (_ + 10)
pure Nothing
Hooks.pure $ HH.div
[ HE.onClick \_ -> Just update ]
[ HH.text $ show intState ]
But in the useLifecycleEffect
block, for example, if I were to refer to the intState
after the call to modify
, or if I were to write some code in the finalizer that used a state value, then I would run into trouble. I'm not actually sure I need to emphasize this as much as I have; folks used to using Halogen already know that something like this won't work:
do
state <- H.get
H.put (state { field = 10 })
-- `state` is not mutable, so this will overwrite the previous `put` statement
H.put (state { otherField = "hello" })
because there's no mutable reference to state. This is heavily emphasized in React articles, but PureScript engineers wouldn't be expecting something mutable in the first place.
I've tried to just cover my tracks by preferring to use get
when I am accessing state in effectful code, but perhaps this just leads to more confusion over when get
would be necessary. I'm open to changing things at least with a note in that section.
Maybe the simplest solution for this particular case is to move the get
call into the returned effect in useLifecycleEffect
, where it really is necessary. This would help demonstrate what sort of case requires retrieving the current value.