Observations on Migrating Halogen Select to use Halogen Hooks

I’m in the progress of porting Halogen Select over to the Hooks style. Here is the main commit that does that (currently untested, but I believe it’ll work). I’m trying to find other ways to clean this up. You can track my progress in my fork’s halogenHooksMigration branch.

Here’s the observations I’ve made during this migration:

Benefits:

  • Queries have been removed entirely. So no need to forward queries or handle them within select anymore
  • I haven’t removed it, but I’m pretty sure the Initialize action is no longer needed as people would use useLifecycleEffect instead
  • No more Input / Record.Builder pattern for modifying the input value that is passed down into the component from the parent. As a result, the end-user can use a non-Record type for their state

Possible improvements

  • For Halogen Hooks, define a type alias to reduce type signature code?
type LibState state = state /\ StateToken state

useHook :: Hook slots output m (LibState Int)
useHook = Hooks.wrap Hooks.do
  (state /\ tState) <- Hooks.useState 0
  Hooks.pure (state /\ tState)
  • Further modulate purescript-halogen-select into smaller hooks that compose together?

Future Refactoring

In my initial “just get it to compile” work, I only converted the component into a hook. I did not refactor handleAction and the functions in Select.Setter to also exist in the single hook. That will be my goal, but I’m not there yet.

Because I haven’t done that refactoring, there are three issues here. First, the user must pass their handleEvent down into the useSelect hook and also into the handleAction. Since these two are separate, it enables the user to use two different implementations of handleEvent, which is not good.
Second, I need to also “return” the search debouncer. Otherwise, it cannot be used in the handleAction code for the component that will use the hook. This exposes internal things that the end-user should not need to care about.
Third, I need to return the stateToken for the hook, which allows the end-user to modify the state of the hook, which could lead to inconsistent state.

The solution (as suggested by Thomas) is to refactor the code, so that it’s contained in the hook. Instead of returning searchDebouncer, the hook would “return” the functions that Select.Setter provides: setToggleProps, setInputProps, setItemProps, and setContainerProps.

1 Like

I believe I’ve finished this (aside from a few stylistic changes). I haven’t yet tested the components out:

Component-Based (before) Hook-Based (after)
Dropdown Dropdown
Typeahead Typeahead

Edit: The above links were updated to refer to a commit rather than the useStateAndTick branch, so that I could delete the component-based examples in a later commit.