I don't know if this is a bug or a misunderstandin...
# compose-web
i
I don't know if this is a bug or a misunderstanding of compose but I created a sample from the template project to demonstrate what we're doing in an app for "Smart"TVs like Tizen/WebOS. We have to listen to key presses from the remote and because the app isn't trivial, we need individual components to listen to global key presses. The issue is that at a depth of 2 composables away from the mutable variable, our key press listeners stop seeing changes to the value. In this demo you can click the button as many times as you like but a single key press will always bring the counter back to 1. If you simply move the counter and increment handler to
CountingScreen
from
Body
the key press handler and click handler both work as expected. Is this a failure on my part to understand how compose works? https://github.com/ToxicBakery/compose-html-keydown-issue/blob/main/src/main/kotlin/main.kt
The obvious part of what is happening is the key down handler only ever sees the initial value of the counter and never sees it change again. I just don't understand why.
a
i dont know how compose html works but make sure you are not re-creating new listeners on every composition. usually you would register listeners in a
DisposableEffect()
and un-register on its onDispose {}.
i
I could be mistaken but that is how
ref
works.
ref
is called back when the HTML element is created and the dispose callback is when it is removed from the DOM. Again I could be mistaken but I'll try using DisposableEffect to see if the behavior changes.
Yep, I can confirm that doesn't change the behavior. It isn't that the registration of the callback isn't working or being assigned multiple times it's that for some reason related to the number of composables between the callback and the function that defined the state, it can't observe changes anymore. Towards the
ref
comment, just for your knowledge. It's my understanding that
ref
is effectively a DisposableEffect with the special feature of giving you the created HTML element as its input enabling you to manipulate it directly in some of the edge cases that compose html doesn't support or to have a good hook point to interact with external JS.
I don't know how far back this goes but it's at least to Kotlin 1.9.x and Compose 1.6.x. Probably further as I believe we've seen this before but we worked around it and couldn't figure out what the replication steps are in a simplified manner like the repo above.