-
Notifications
You must be signed in to change notification settings - Fork 32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add useStateConst where update is always const #24
Conversation
Thanks for the PR! I'm a little hesitant to merge this for two reasons, though:
With both of these considerations in mind, I'm not sure making the api busier is worth it. As for why the update pattern should be encouraged, it's primarily to avoid race conditions. Even "atomic" values like numbers and strings can run into issues. For example, this code has a bug: counter /\ setCounter <- useStateConst 0
let increment = setCounter (counter + 1) It ties the effect of incrementing the counter to the way React chooses to dispatch renders. If counter /\ setCounter <- useState 0
let increment = setState \c -> c + 1 If it helps, let increment = setState (_ + 1) -- assuming the state record has other fields as well:
let openModal = setState _ { isModalOpen = true } But be careful to avoid -- notice, "toggle" instead of "open"
let toggleModal = setState \s -> { isModalOpen = not s.isModalOpen } Sometimes constant values do make sense. I've found, however, that it's often more specific to the type of update than it is to the type of state. The counter example works well here too: counter /\ setCounter <- useState 0
let increment = setState \c -> c + 1
let reset = setState \_ -> 0 Here, a It's also very easy to get the behavior counter /\ updateCounter <- setState 0
let setCounter c = updateCounter \_ -> c
-- or
counter /\ setCounter <- rmap (_ <<< const) <$> setState 0 By the way, I usually find things read better when low level hook usage is packaged away in component-specific hooks. It often removes the component "Counter" \props -> React.do
counter /\ setCounter <- useState 0
let increment = setState \c -> c + 1
let reset = setState \_ -> 0
pure $ ...render some things Could instead be written like this: component "Counter" \props -> React.do
{ counter, increment, reset } <- useCounter 0
pure $ ...render some things
where
useCounter initialValue = React.do
counter /\ setCounter <- useState initialValue
let increment = setState \c -> c + 1
let reset = setState \_ -> initialValue
pure { counter, increment, reset } |
Hi @spicydonuts thanks for reviewing. You're right that whenever an update function is needed, then I'm not proposing the Consider a react component with a form with 10 fields. Using hooks, we'd normally write 10 separate Another place that the const version of the Last note is on my codebase that use this awesome purescript-react-basic-hooks, I normally name the setter side as
And then usually create an alias:
Normally though I don't ever use the |
Hmm.. I see what you mean. That React docs example is unfortunate though. 😅 What do you think of calling it |
I definitely prefer |
A common use case of
useState
does not rely on the update function. AddinguseStateConst
to address this. Not sure if I chose the best name though.