darklang / rescript-tea

The Elm Architecture for Rescript
Other
118 stars 9 forks source link

Modularized TEA structure #58

Open paulstadler opened 1 year ago

paulstadler commented 1 year ago

Hi there,

Amazing work in this package. I'm trying to scale it to a SPA here. Initial goals are:

I think this will help contain changes - it's also what folks in elm-land are doing. So I'm thinking along those lines.

The challenge I'm having is that the messages coming back from each page aren't able to map back up to a global message type.

When messages are attached to an action in the view function, they seem to translate to a JS tag that's typeless and gets unintentionally casted when it comes back in update.

I've tried to solve with something like this:

let view = (m: model): Vdom.t<msg> => {
  let pageView = switch m.path {
  | "/home" => Vdom.map(a => HomeMsg(a), Home.view(m.home))
  | "/payments" => {
    let v = Payments.view(m.payments)
    Js.log("pre map")
    Js.log(v)
    Vdom.map(a => PaymentsMsg(a), v)
  }
  //| "/events" => Vdom.map((a: CoreEvents.msg): msg => CoreEvents(a), CoreEvents.view(CoreEvents.init()))
  | _ => text("undef route: " ++ m.path)
  }

... and that compiles fine. However, the events don't actually get mapped to the correct msg type.

Please forgive me if the solution is obvious -- I'm new to rescript! (Loving it btw...)

I've dug in vdom.res pretty substantially and understand that it's wrapping taggers in there etc.

Would it be possible to show an example of how to handle messages that are variants of msg types in other modules? I'm looking for something like this:

type msg =
  | AppBarMsg(AppBar.msg)
  | HomeMsg(Home.msg)
  | PaymentsMsg(Payments.msg)
  | CoreEventsMsg(CoreEvents.msg)
  | LocationChange(string)

at the top level.

If there were a function in the tea library to help with this it would be most beneficial!

Thanks so much! Paul

paulstadler commented 1 year ago

I dug into this a bit more. What's happening is that the event signatures inside the vdom (cached) are updated only when their callback or the TAG# or name changes (I might have that a little off...). Since local msg types all translate to tags 1, 2, 3 etc... it can't tell that there's a new type being used inside the cache. The name's are all "click" for my test.

Not sure how this would be addressed. It is true that the underlying javascript callback should be different... but that didn't seem to matter. It would be interesting if there were a way to make TAG #'s unique across the whole app when compiling down to JS. That would probably solve it as well... might break other things.

I started down road of completely rebuilding the vdom (to encapsulate local msg types into a global variant of msg), but gave up and just made all messages global for now. That works well... but it's not optimal. Would be great to hear your thoughts on it.

Thanks! Paul

pbiggar commented 1 year ago

I'm not sure I follow this entirely, but some thoughts based on our codebase.

We use global types pretty much - we were slowly moving towards encapsulation (fyi, we've stopped using the product with the rescript codebase). See https://github.com/darklang/just-fluid/blob/just-fluid/client/src/app/AppTypes.res#L1183 for what that was like.

One other thing that comes to mind is that rescript-tea exposes keys, which elm I think does not. See discussion here: https://github.com/darklang/dark/blob/ca40124dd25a0938a8bc99a3e694b534b84a2855/docs/bs-tea.md

Not sure if that's helpful?