thomashoneyman/purescript-halogen-hooks

HalogenIO.dispose doesn't remove Hook-based components

JordanMartinez opened this issue · 4 comments

Compare these two implementations of a component that loads and is removed after 2 seconds via HalogenIO.dispose:

The Halogen one removes 'Loading' from the page whereas the Hook one does not.

This problem still exists even when I make the Hook component a render-only component, which tells me Hooks.fork isn't an issue here:

loading :: forall q i o. H.Component HH.HTML q i o Aff
loading = Hooks.component \_ _ -> 
  Hooks.pure $
    HH.h1_
      [ HH.text $ "Loading" ]

I don't yet know why HalogenIO.dispose doesn't remove the hook-based component. For anyone who runs into this bug before it's ironed out -- if you need to use dispose at the top level, then keep in mind that ordinary Halogen components are properly disposed of. So long as the root component is a normal Halogen component you are OK.

I took a look at this over lunch. This is a bug in Halogen in which dispose tries to remove the VDom tree that existed when the root component was initialized, not the one that exists when it is disposed of.

This ordinarily isn't a big problem -- dispose removes the root of the VDom tree, and for your root component that probably hasn't changed over the lifetime of your application. But Hooks-based components first render an empty text node and only render your desired HTML after the first Hooks evaluation. That means dispose will always fail on a Hooks component due to the bug in Halogen's dispose implementation.

purescript-halogen/purescript-halogen#675 describes this issue and purescript-halogen/purescript-halogen#676 fixes it.

You can see via this Try PureScript reproduction that this isn't a Hooks-only problem -- it's a problem for any Halogen component that renders a different root element after its first render:
https://try.purescript.org/?gist=4c7f24a18ac9120b715c95b0b769d3f9

Closing as this is fixed as of Halogen's v5.0.2 release.

Nice investigative work there!