While individual HyperViews can only have one update in progress at a time, multiple HyperViews can overlap updates without issue
By default, if an Action triggers for a particular HyperView when one is already being processed, the system will Drop the newer action without running it. This prevents destructive actions from accidentally happening more than once.
However, some user inputs only load data and overlap many times, such as an autocomplete or mouse events. In these cases, it can be better set the Concurrency of the HyperView to Replace. This will cancel the currently running action, and immediately run the new one instead.
instance (Debug :> es) => HyperView OverlapReplace es where
  data Action OverlapReplace
    = GetTimeReplace
    deriving (Generic, ViewAction)

  type Concurrency OverlapReplace = Replace

  update GetTimeReplace = do
    t <- getTimeSlowly
    pure $ viewTimeReplace (Just t)
See Autocomplete for a complete example
Instead of preloading everything in our Page, a HyperView can load itself using onLoad
viewTaskLoad :: View LazyData ()
viewTaskLoad = do
  -- 100ms after rendering, get the details
  el @ onLoad Details 100 ~ bg GrayLight . textAlign AlignCenter $ do
    text "..."
By including an onLoad in every view update, we can poll the server after a given delay
viewPoll :: Int -> View Poller ()
viewPoll n = do
  -- reload every 200ms + round trip delay
  col @ onLoad (Reload (n + 1)) 250 ~ gap 10 $ do
    row ~ gap 5 $ do
      button (Pause n) "Pause" ~ btn
      button Stop "Stop" ~ btn
    viewStatus n
Actions can call pushUpdate to send an intermediate update to the view. This can be simpler than polling. If another
  update RunLongTask = do
    forM_ [1 :: Float .. 100] $ \n -> do
      pushUpdate $ taskView (n / 100)
      delay 50
    pure $ taskView 1
  update Interrupt = do
    pure $ col ~ gap 10 $ do
      el "Interrupted!"
      taskView 0