I’m using the master branch of Halogen, so I’m not sure if this is related to the current released version. I have a parent component that reads the current path and displays the correct child component depending on the path. One such path is “/players/bklaric” that shows information about player “bklaric”. The parent component render function for this case is: render (Player nickname) = HH.div_ [ topBar, player nickname ], where player is the child component defined as:
data Query send = Init String send
...
component :: forall input left.
String -> H.Component HH.HTML Query input Void (Async left)
component nickname = H.component
{ initialState: const Empty
, render
, eval
, receiver: const Nothing
, initializer: Just $ Init nickname unit
, finalizer: Nothing
}
player
:: forall query children left
. String
-> HH.ComponentHTML query (player :: Slot Unit | children) (Async left)
player nickname = HH.slot
(SProxy :: SProxy "player") unit (component nickname) unit absurd
The eval case for the Init query constructor loads the player info and changes the component state to display the info. This works fine except in the case when the path changes so that the player component is the component to be rendered again, e.g. from path “/players/bklaric” to “/players/idunno”. My expectation was that the initializer would get called again and the component updated, but nothing happens. No request is sent to retrieve information for player “idunno” and the component stays the same. After fiddling around with it, I got it to work by specifying a receiver function and passing the nickname both as an input and to the initializer:
component :: forall left.
String -> H.Component HH.HTML Query String Void (Async left)
component nickname = H.component
{ initialState: const Empty
, render
, eval
, receiver: \nickname' -> Just $ Init nickname' unit
, initializer: Just $ Init nickname unit
, finalizer: Nothing
}
player
:: forall query children left
. String
-> HH.ComponentHTML query (player :: Slot Unit | children) (Async left)
player nickname = HH.slot
(SProxy :: SProxy "player") unit (component nickname) nickname absurd
This seems weird to me, because:
- I feel it breaks the declarativness of the library, because I have to take into account from which states can the parent component come into some other state.
- The nickname being passed as input seems to be ignored by the receiver when the component is first initialized, but is then ignored by the initializer when the component is already there.
Am I missing something here? Is there a better way to achieve this kind of use case?