karaxnim / karax

Karax. Single page applications for Nim.
MIT License
1.05k stars 90 forks source link

view doesn't update when changing state in setInterval #243

Closed Athlon64 closed 1 year ago

Athlon64 commented 1 year ago

Minimal code as follows:

include karax/prelude
import karax/kdom

var v = 10
proc update() =
  v += 10
  # redraw()
discard setInterval(update, 200)

proc main(): VNode =
  result = buildHtml(tdiv):
    text $v

setRenderer main

The view won't get update unless calling redraw() explicitly.

geotre commented 1 year ago

This is expected. Karax's reactivity model is different to mainstream frameworks (like React and Vue). They implement it by creating reactive state with useState/setState etc. Karax instead reacts to events, similar to things like Elm.

This approach is perhaps simpler and easier to reason about, with the tradeoff being that events need to be wrapped to trigger a redraw. Karax does this for you with dom event handlers, ajax network calls, etc, but you will need to add it for things outside of that (websocket messages, document timing functions).

So the recommended solution would be something like:

include karax/prelude
import karax/kdom except setInterval

proc setInterval(cb: proc(), interval: int): Interval =
  kdom.setInterval(proc =
    cb()
    if not kxi.surpressRedraws: redraw(kxi)
  , interval)

var v = 10
proc update() =
  v += 10
discard setInterval(update, 200)

proc main(): VNode =
  result = buildHtml(tdiv):
    text $v

setRenderer main

Does that all make sense?

Athlon64 commented 1 year ago

I got it. Many thanks, @geotre, your explanation is crystal clear. By the way, I really think we should put this in the document.

geotre commented 1 year ago

Thanks for the suggestion @Athlon64, I have added it!