thomashoneyman/purescript-halogen-hooks

Button and Container example not working outside of storybook

milesfrain opened this issue · 2 comments

After copying this Button and Container example to a halogen template, queries to the child component are no longer working. The parent always says the button is off, even when the label changes.

The only different I can think of is how the component is being launched:

main :: Effect Unit
main = HA.runHalogenAff do
  body <- HA.awaitBody
  runUI Container.component unit bod

I wouldn't expect running Effect in Aff would cause problems.

Here's the template branch with the broken example.
https://github.com/milesfrain/halogen/tree/container/src
Reproduce with:

npm run serve

This is happening because the Hooks is at version 0.2.0 in the package set for that repository (the May 7 package set).

In that version of Hooks the useQuery handler was only defined on initialize, and not on every render. That meant it worked fine if you used Hooks.get internally, but if you referred to a state variable directly it would get stale over the subsequent renders.

  enabled <- Hooks.useState false
  Hooks.useQuery tokens.queryToken case _ of
    IsOn reply -> do
      pure (Just (reply enabled))

Here, enabled is false on the first render, and the useQuery handler closes over the value. So the same handler, now essentially hardcoded to return false, gets called on any query. The current version of Hooks (0.4.0) handles this differently: on every render the useQuery handler is refreshed, so there's no issue with closing over values like enabled here.

If you update to the current version of Hooks (0.4.0) -- which is in the current package set, but the package set hasn't yet had a new release -- then your example should work again. Alternately, you can do this:

  Hooks.useQuery tokens.queryToken case _ of
    IsOn reply -> do
      enabled' <- Hooks.get enabledId
      pure (Just (reply enabled'))

Thanks. I installed the latest by manually adding to packages.dhall as described here, and it now works.