Hacker News new | ask | show | jobs
by tdbgamer 2951 days ago
I really liked Elm a lot, but the issue for me was that composing components is a shit show. You have to add variants to the root Msg type for every single subpage and have it dispatch to the right update/view functions.

I'm really excited about a project inspired by Elm called Yew but allows you compose components much more naturally and easily.

https://github.com/DenisKolodin/yew

2 comments

I really liked Elm a lot, but the issue for me was that composing components is a shit show. You have to add variants to the root Msg type for every single subpage and have it dispatch to the right update/view functions.

Doesn’t that make sense, though?

An app in Elm is some kind of state + messages that change the state. Since the state is usually too big to fit in a single structure, you break it down recursively into progressively smaller substates. These again have some messages that mutate the state.

Now, doesn’t it make sense to send the “child” messages through the parents? You shouldn’t command the children directly, you should always tell the parent to tell the child do this and that. At least in our [Swift, not Elm] app that makes sense, composes well and keeps the model simple to think about.

Not op, so I don't know his/her struggle. My struggle comes maybe from the syntax I'm not used to, but also it always feels like you have to keep the whole message-graph in mind to understand which message comes from where and goes where and needs to contain which data and while that type system helps, it feels like it also makes it more difficult. You cannot just run it and see how far you come, you're code just won't compile. I know, this is a good thing for bug free production code, but exploration is harder (at least for me).

Also the types become really complicated after a while since you wrap everything in some kind of message type. So your parent message contains a child message, containing some data that needs to get passed to the next view. So errors become less readable or helpful. Or I'm doing something wrong, which could very well be because I'm a bloody beginner.

[I]t always feels like you have to keep the whole message-graph in mind

It should be quite the contrary. When you design a piece of the app, the piece should have its state, messages and view code, so it should be perfectly possible to ignore any context, focusing just on the single piece. Just like when writing pure functions, for example.

You cannot just run it and see how far you come, you're code just won't compile.

This is a known initial hurdle with expressive static type systems I think. It gets better quickly and then you won’t be able to go back, feeling existential fear without the compiler watching your back.

So your parent message contains a child message, containing some data that needs to get passed to the next view.

This is getting too particular for me to explain/help/argue directly. In our app, for example, the main app model is either onboarding, home screen or signed out. Then it makes big sense for the main model to accept messages regarding onboarding, home screen or signed-out state. And when it receives a message related to one of its child states, it just delegates it. This makes sense conceptually and is quite natural to follow when reading the code.

I am not an experienced Elm programmer, so maybe I am getting this wrong, but what we have has worked for us well, so far.

When I was a beginner, I found this extremely slow & burdensome. So much boilerplate!

Working in a huge codebase, I don't feel this pain at all.

I wonder if the beginner experience is off. When you add functionality to a huge application, the ease of threading through state is so much easier than just always winging it like I used to.