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 useuseLifecycleEffect
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
.