The SquareButton and CircularPinkButton are nothing but components wrapping/composing the BasicButton with some default state.
The data layer is still plain-old imperative. But with declarative UI, its generally better if the data layer is reactive in nature, so that UI state manipulations can depend on that. There are a ton of ways on how to structure the data flow in apps that use state driven Ui frameworks like redux, flux, custom MVX. The choice entirely depends on the kind of the app, underlying framework, expertise of the team, etc.
Benefits:
Loc--
Looks like its obvious from the code example shared above. The line of code has reduced by quite a bit.
Flutter & React native here provide extra benefit of being cross-platform, hence the reduction in loc with these will be a lot more.
Readability++
The UI code is certainly more readable and easy to reason about.
Composability
The very fact that all the UI components are based on some state permutations and/or combinations of smaller basic components makes the code ultra reusable.
UI Replication
This benefit actually comes from the State driven UI. Where given a permutation of state, one can easily figure out the UI. Now this is actually the most underrated benefit of state driven UI. Using this concept one can practically come up with a UI documentation (aka component library) for an entire software/app. And anybody can visualise how a particular component will look given this state. React storybook is one such tool that is built around this philosophy.
Better UI testing
Composability & UI replication brings us to the next obvious point: Better UI testing.
Writing Unit tests become super easy for the declarative UI components. One just needs to manipulate the state and query the UI accordingly.
Downsides:
Not many, but for the sake of it:
Learning Curve
For imperative programmers, declarative UI code might be not-so-obvious to begin with. Understanding the internals of declarative UI frameworks might also take a lot of brain cycles.
Performance
One has to be very careful when dealing with endless scrolling, dynamic content in lists etc. Because if the UI state is changing very frequently and the code is poorly optimised, it can give some serious UI janks.
On top of it, every declarative UI framework comes with its own implementation of how UI diffing is done which leads to framework specific nuances and different kinds of optimization that these frameworks demand.
Closing the entire loop!
- Jetpack compose uses a gap buffer datastructure to calculate the minim possible UI updates that are required. (https://medium.com/androiddevelopers/under-the-hood-of-jetpack-compose-part-2-of-2-37b2c20c6cdd)
- React creates a Virtual DOM tree. (https://reactjs.org/docs/faq-internals.html)
- Flutter uses Element Tree and Render tree to do the same. (https://flutter.dev/docs/resources/architectural-overview)
WHOA!
That was quite a ride through the modern mobile UI and its evolution. This article doesn’t even touch the surface of the modern UI frameworks but can give a general sense of what is happening on the UI development. With Apple pushing swift UI, Google coming up with jetpack compose and flutter and react being here for quite some time; all of this is a testimony to the fact that Declarative UI is the future.
Advanced topics [Stories coming in the future]
- Comparing UI diff internals of Flutter | Jetpack Compose | React
- Comparing performance of Flutter | Jetpack Compose | React
- Dataflow [data layer in declarative UIs]
- Primary and secondary components, MVXs
Thanks to Tavishi Jain and Omolara Adejuwon.