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
Initializeaction is no longer needed as people would useuseLifecycleEffectinstead - No more
Input/Record.Builderpattern 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-Recordtype 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-selectinto 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.