Skip to content

The semantics of render is very fragile #20

@dramforever

Description

@dramforever

Steps to reproduce

module Main where

import Transient.Base
import Transient.Move
import GHCJS.HPlay.View

import Data.Functor (void)
import Control.Concurrent (threadDelay)
import Control.Monad.IO.Class (liftIO)

main :: IO ()
main = void . keep . initNode . onBrowser . local $ do
  name <- render $ inputString Nothing `fire` OnKeyUp
  content <- liftIO $ do
    threadDelay 500000 -- simulate a delay
    pure ("Hello " ++ name)
  render $ rawHtml (p content)
  1. Build and run this
  2. Type 1234567890 at about 5 key strokes per second

Expected behavior

After it settles, I expect either

  1. 10 lines appearing, saying

    Hello 1
    Hello 12
    Hello 123
    ...
    

    and so on, one for each keyup event, or

  2. one line appearing, saying

    Hello 1234567890
    

    corresponding to the last keyup event

Actual Behavior

I only some of the corresponding lines.

If we think the action of getting content as a request, then the displayed results are the responses that arrived after the last event, whereas I expect either all or one response corresponding to the last to be displayed.

Observations

As I've shown in the example, this does not need to have atRemote to happen.

Replacing liftIO with async doesn't help

What does this have to do with render

I believe this behavior of render, is causing this:

If an event happens within the render parameter, it deletes the rendering of all subsequent ones.

But when the content has not arrived, the subsequent render is non-existent, so it is not affected by this. I believe this, although documented, is what's causing the strange behavior of the example program.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions