问题
in the simplest case, say I have a Dynamic t Bool
, and when the value is true, I want a single empty div to exist, and when the value is false, I don't want there to be any dom element.
slightly more generally, if I have a Dynamic t (Either MyA MyB)
, and I have functions that know how to render given a Dynamic t MyA
or a Dynamic t MyB
, how to I call the appropriate function to render?
回答1:
If you need to switch the widget you probably need one of:
dyn :: MonadWidget t m => Dynamic t (m a) -> m (Event t a) Source
or
widgetHold :: MonadWidget t m => m a -> Event t (m a) -> m (Dynamic t a)
Since you've mentioned you've got Dynamic at hand, we're gonna use dyn
:
app = do
switched <- button "Alternate!"
flag <- foldDyn ($) False (not <$ switched) -- just to have some Dynamic t Bool
let w = myWidget <$> flag
void $ dyn w
myWidget :: MonadWidget t m => Bool -> m ()
myWidget False = blank
myWidget True = el "div" $ blank
The basic rule is that, due to the higer-order nature of Reflex, if you want to swap-out something, you need to have Event/Dynamic that yields a widget as a value. That's why dyn
takes Dynamic t (m a)
as its parameter (and appropriately, widgetHold
takes Event t (m a)
. And that's why we've mapped over Dynamic t Bool
to have a dynamic that has our widget building action as a value.
It's worth mentioning, that neither dynamic/widgetHold does virtual dom/diffing to speed the rendering. With reflex you can be more explicit about what updates what (a Dynamic/Event t Text can affect node text directly, without rerendering whole node) and you should take advantage of that. If not then large portions of page will be swapped and it can yield significant performance hit.
来源:https://stackoverflow.com/questions/40481916/how-can-i-branch-on-the-value-inside-a-reflex-dynamic