I've written a deep dive comparing Angular and Com...
# feed
c
I've written a deep dive comparing Angular and Compose. Of course, only Compose is available to Kotlin developers, but I still believe it's important to learn from other frameworks. https://ivan.canet.dev/blog/2025/02/10/angular-compose.html
👍 6
👍🏽 1
👍🏻 1
❤️ 2
r
The
Counter
composable function will definitely not compile 😉
t
Interesting article, thank you for the work put in. While I agree with many points in it, I've always felt the Compose has way too much boilerplate and the syntax is very ugly (as code). For example, these I never, ever want to write. These are between the reasons why I don't use Compose (I write almost exclusively KMP code, mainly UI, mostly browser).
Copy code
var value by mutableStateOf(0)
val isEven by derivedStateOf { value % 2 === 0 }
Because I like to write this (actual, working, reactive code):
Copy code
var value = 0
val even = (value % 2 == 0)

box {
    onClick { value++ }

    if (even) {
        text("even")
    } else {
        text("odd")
    }
}
I always felt the the idea of Compose is amazing. But the actual technology I have to use is very restrictive, hard to read, missing quite a few features (especially on web). I feel that being born on Android is a bit too heavy of a legacy.
c
@Robert Jaros what's wrong with it? 😅
@Tóth István Zoltán what technology do you use for your example to work? I don't know of a framework that can track state without wrapping it
r
@CLOVIS Never heard of using
val
as function parameter 🙂 And
onChange
should be
(Int) -> Unit
and not
() -> Int
. At least my "in memory" compiler says that ... it can be wrong ... 😉
c
ouch yeah, can't believe I missed this
r
Still a great article!
🙏 1
c
should be fixed in a few minutes
t
@CLOVIS https://medium.com/@tiz_26128/a-life-without-compose-5b77a9a8129f To be honest, I really don't like the extreme focus on Compose. I feel that it is one of the reasons KMP is struggling with gaining wider audience. The best example is multiplatform resources. Which is actually impossible to use without Compose (hence, I had to copy the gradle plugin code and write my own).
c
Yep, 100% agree. I prefer Compose for Web than Compose UI, and there's basically no tooling available.
t
That missing tooling is one of the pain points. That's why I am actually writing one...
e
Btw, instead of discussing about Angular signals in the change detection chapter, I'd have presented the
OnPush
strategy. Even with signal inputs and outputs,
OnPush
is the preferred strategy to avoid unnecessary change detection cycles on unchanged component trees.
Note that you may use signals in Angular components without
signals: true
, for example to profit from the greatly simplified lifecycle management, but you will access any of the performance benefits then.
When using
OnPush
- even without signals - this part isn't true anymore.
c
I'm not sure I understand what
OnPush
does. I've never seen it used in real life. From the docs, it seems to imply change detection happens whenever an input changes or whenever an event is fired, but that's already the default strategy 🤔
e
OnPush
optimizes the change detection cycles by not processing component trees where input values haven't changed since the last run. The default strategy will always do a pass on all trees and re-render their content.
It's pretty much a default in decently-sized SPAs to avoid frame drops
c
But it still processes components based on their events? What happens if you change a local value as a result of an httpClient call?
e
If you perform the HTTP call inside the component, and you simply update a local property (e.g.
example: string
), the component isn't marked as dirty, so the change detection run spawned by zone.js won't update its presentation.
Note that Angular can also work zone-less now.
Generally, that's why HTTP calls are performed via Angular's
HttpClient
, so that you can subscribe to the result via the
AsyncPipe
which will then call
CDR.markForCheck()
whenever the value has changed.
c
I guess that's why we don't use
OnPush
then, if it can't track local state changes.
e
Yup. All changes should be top-down via
@Input
, or be tracked using observables/signals when using local state in templates.
c
That makes the TS class of the component even less useful than it currently is… Not that I'm complaining. It's interesting to see how Angular devs often complain that React is not structured enough, but then their best practices often go against using that structure. 🤔
e
> That makes the TS class of the component even less useful than it currently is Not sure what you mean specifically by this, but generally speaking we use the smart-dumb component approach. Most of our components will be "dumb" in the sense they won't contain any local state (well, they might if the presentation gets complex tho), and a small subset will be "smart" and aggregate those dumb components, keeping state using signals or observables, be it local or coming via services.
but then their best practices often go against using that structure
This one specifically is not clear to me. The structure and usability of Angular is based on RxJS, so every use case was studied based on how to better integrate reactivity in templates, without incurring in performance costs.
c
Not sure what you mean specifically by this
• UI code should go in the template • Component state should be either in inputs or in observables ; ◦ inputs are controlled elsewhere ◦ observables should be controlled by services • Binding to an observable should be in the template (to use
| async
) there's not much else that could be in a component class
e
there's not much else that could be in a component class
You still have event handlers, for example. But I get what you mean. Although I do like having clear separation between template and TS code (that's the whole argument against React), there are people that choose to use inline templates and inline styles, so that they have a single TS class for everything that is needed.
> You still have event handlers, for example. And the various
@ViewChild/ren
,
@ContentChild/ren
,
@HostBinding
,
@HostListener
c
How often do you use these? I tend to very rarely use any of these
e
They are indeed rare, but the concept I like about Angular is I always know where things are, no matter the codebase I'm looking at.
c
Although I do like having clear separation between template and TS code
Personally I prefer separating between "UI glue" and "component logic", which React/Compose let me do (but don't enforce). With Angular, I often find the component mostly contains trivial getters or setters for the template, and only a few meaningful things
k
the only thing stopping me from using compose for web is SEO else everything is fine
v
The article is about Compose HTML though which uses HTML / DOM and is Stable, not Compose Multiplatform for Web which draws on a Canvas and thus lacks SEO and dev tools support and is Alpha. 🙂
c
Yep, Compose HTML basically has the same SEO story as React. When coupled with #C04RTD72RQ8's static pages, SEO is as good as any other web framework.
v
While Kobweb is not production-ready as far as I read yesterday on its docs
c
Depends on your definition of production-ready. It works, and multiple companies use it in production. There are breaking changes once in a while, but nothing compared to Angular's breaking changes 😅
v
Ok, then I maybe misread its readme