UIs are not pure functions of the model (2018)
blog.metaobject.com
blog.metaobject.com
So obvious they are left as an exercise for the reader?
This whole article seems to be based on the idea that pure functional programming is absurd and impossible, and this is just obvious and doesn't need to be shown. For someone who has written a decent amount of Elm, it certainly isn't obvious to me.
Specifically "UI is not a pure function of a little pile of centrally defined state" is just this assumption that isn't true, Elm literally gives you no choice, you only have that, and it works, so it clearly can be.
It also ignored all the value you gain from doing it that way. As I say, I've written a fair bit of Elm at this point, and it can often be verbose which can be annoying, but it is actively not complex in the best way, with it being very easy to reason about and bulletproof once it compiles.
Huh? Where?
> The idea of UI being a pure function of the model seems so obviously incorrect, and leads to such a plethora of problems, that it is a bit puzzling how one could come up with it in the first place, and certainly how one would stick with it in face of the avalanche of problems that just keeps coming. A part of this is certainly the current unthinking infatuation with functional programming ideas. These ideas are broadly good, but not nearly as widely or universally applicable as some of their more starry-eyed proponents propose (I hesitate to use the word "think" in this context).
The pure function approach is simple enough that they could include the code in their blog. The other approach wasn't included.
I don't think that was ever the claim, the rest of the article is similarly misguided. UI as a function of state doesn't mean "UI is a function of business logic state". It means we define the UI in a declarative way based on the view state.
In Cocoa, scroll position is part of the view's state, a mere property of the view. This is simple because the UI itself is stateful.
In React, scroll position is typically not part of the state from which we project the view. Instead this state is attached to the projection itself (e.g. a HTML node) and we are dependent on the "Memoization Map" to preserve it. So this memoization is now required for the correct functioning of the app. The "pure function" abstraction is leaking.
I see the “abstraction leaks” as a feature, not a bug. It means React is flexible enough to handle the real world, which is a lot messier when things go async or interactive. Re-rendering due to mouse position without :hover CSS and friends would be incredibly painful.
Also, I have worked on React apps that tracked scroll offsets. This is common (sadly) when managing back and forward state in a single page app as you might want to show a new page on-click and “scroll to the top” but then click the back button “and scroll back to where you left off” and not have the page actually reload for either of those interactions.
Not saying it’s pretty, but it’s certainly possible to need to track scroll offsets. My preference would be to layer stateful scroll-offset views otherwise rendered by pure functions on top of each other and when you go back, just pop a view off the stack, but not all SPA frameworks are designed that way.
The typical approach would be to attach an event listener to a scroll event or to an IntersectionObserver and then set a state property from that.
Memoization is supposed to be purely a performance enhancement. I would never use it for handling scroll position.
If you define your state broad enough everything becomes a declarative/pure functions. That's not the point of interest, it's that React doesn't (and can't thanks partially to the DOM) handle view state super well. You can't make the complexity disappear so without using side-effects like useState/useEffect it lives either the model (current typed text) or the internal state of the DOM node (scroll position).
rel/to title: yes. (just say scroll position. fine.) But also I think this is pretty well understood! (No?)
- In declarative UI / FRP / whatever, you model your basic UI state through a pure mapping from your business logic 'model'.
- But (as in procedural programming) the UI has its own state — that's not necessarily part of your initial business/domain/model.
If you want to model it, you'll have to understand it, read it, and add it to you model. That can be annoying—especially if the APIs for getting or setting the state are bad.
This doesn't really sound like a fundamental flaw conceptually to me. It's just an API with defaults you don't have to deal with unless you need to.
- don't care what your color is? fine. system default for you.
- don't care what tab a link opens in? fine. user default.
- don't care how scroll position is managed? fine. system default.
- want to handle any of them? cool. you can.
It sounds like progressive disclosure of API complexity to me. Great.
React obliterated their world view and they simply could not cope.
I am using hyperbolic language but the "Anti-React" 'backlash' was truly mind boggling.
This makes testing simple as you can test the reducer without rendering any UI. The pure view components are also easy to test. Then a few end to end tests to tie everything together.
https://www.reactguide.dev/#mc-v-trees Has more info on how to scale the pattern for larger apps.
I had only seen these misunderstandings in talks (particularly the "cascading", which true MVC absolutely prevents), which are difficult to refer to, so thanks for the link!
As I wrote elsewhere[1] : "having to say "the problems of MVC are solved by MVC" is less than ideal, because, well, you sound a bit like a lunatic."
[1] https://blog.metaobject.com/2017/03/concept-shadowing-and-ca...
2. Controllers, like views and model(s) are roles, not components. These roles can be filled by the same objects.
3. So people not agreeing where things go is perfectly compatible with MVC, and thinking that's a problem is a symptom of not understanding MVC.
4. I personally try to put as much as possible (and a bit more) into the model. Hexagonal for the win! Naked objects are also pretty nice, though I tend not to be quite that radical.
¯\_(ツ)_/¯
They just don't have to correspond to specific and distinct components.
This is all explained in detail in the documentation, which is really helpful for understanding MVC.
In my experience with React, it's a lot harder to keep things separated, and developers who I've worked with who have more React experience aren't always up on the concept.
Still consider myself anti-react. It's a leaky abstraction.
This is not coping! It is speaking truth to deniers.
This is a tangent, but the implicit assumption that the UI is visual is just begging for a response from an accessibility perspective, so here goes.
Accessibility is very much an afterthought in native GUIs, not only in Cocoa, but also in Windows with the UI Automation API, and AFAIK with other native accessibility APIs as well. With these APIs, the assistive technology (e.g. screen reader) pulls information from the application (usually via the GUI toolkit), through repeated calls to methods defined by the accessibility API. Often the AT has to do several such calls in a row (and those often translate to multiple IPC round trips, making things slow). And the UI might change between such calls; there's no guaranteed way to get a consistent snapshot of the whole thing, as there is with a visual frame. On the application/toolkit side, these methods may return different responses from one call to the next, and the application or toolkit has to fire the right events when things change.
The web improves on this, in that accessibility information is conveyed through HTML tags and attributes. And yes, this is included in the output of a React component's render function. So while in practice, implementing accessibility may still be an afterthought, it's not an architectural afterthought as it is in native platforms.
One of my goals in AccessKit [1] is to work around this shortcoming of native accessibility APIs, particularly for developers of cross-platform non-web GUI toolkits. In AccessKit, the toolkit pushes a full or incremental accessibility tree update to the AccessKit platform adapter, which maintains the full tree in memory and uses that to implement the platform accessibility API. This even works for immediate-mode GUIs, as one can see in my proof-of-concept integration with the Rust egui toolkit [2].
My take is that it's the growing complexity of web development (yes, React has some responsibility here), combined with the constant influx of new developers, that's largely to blame for any overall proportional loss in the practice of accessible markup.
If a React dev leans on an accessible UI framework like Chakra, or Headless UI, or React-Aria, they're probably better off from an accessibility perspective than a dev that tries to implement WAI guidelines from scratch.
I think Marcel brings up a valid point about composition, if I understood it correctly. The composition of interfaces in Dolphin Smalltalk, for example, is super easy with the MVP paradigm. You can build and test a particular feature and immediately drop it into another, larger composite presenter. You just make its model a field on its owner. Other properties can be connected to where they need to be during the initialization of the component.
I'm not sure if wiring up react components is as easy, because you have to think about stuff that is not directly in your data flow. But I honestly don't have enough experience to say. I have more experience with Elm and found it a little less easy.
At that point, the big difference between MVx and reactive is the bidirectional data flow in MVx. Parts need to be bound so that they update the real world, and updates need to be observable so the UI can change. Reactive UI coordinates a filtration of that state through the view painting.
In Elm (old Elm, not sure what it's like now) when you embed a component your top level needs to understand its messages to pass them down/up appropriately. The type system helps you not forget things, but there was a good bit of retyping.
That, and the way that html bits fit into other bits breaks the abstraction. Perhaps using a reactive approach to run Web Components is the best way to get the same sort of composability currently, I haven't tried it.
Alerts and login forms are clearly prompts. But so is an complex editor: it constantly prompts the user for the next action, e.g. enter text or change existing text’s formatting. Or a social-media site: possible actions are “login”, “view post”, “create post”, and so on.
Even an FPS can be warped into a prompt-based UI, where the model is the game state (or what the player sees of it), and the prompts are “move, turn, shoot”. But you probably shouldn’t do that. Asp bad examples: a weather or stock viewer where your options are null, and the model is the weather or stock which you can’t change.
Nonetheless prompt-based UI is really useful for many otherwise-ordinary cases. It lets you write a UI like a CLI and automate your UI very easily; it tells you which state is truly part of the “model” and which is just part of the UI; it’s composable spatially (more elements) and temporarily (series of steps). I don’t know if it’s been explored much.
In prompt-based UI, the UI is sort of a pure function of the model. It’s an asynchronous function which takes the model and returns a stream or future of the next action(s).
However, there are definitely some problem domains that don't map very well to the React model. Real time games, for example, have very different requirements.
If you need a very long list in React, you need to use a library with quite weird API.
I think the author's analogy breaks down here. Almost every point after this is "You don't need this because React started from this faulty assumption that UIs aren't stable".
The hand rails frameworks like React gives you is because this assumption isn't true. If your UI is stable enough where this complexity isn't needed, then don't use React.
Richard Harris takes the same tact. He describes “UIs as a function of state” as an ideology: https://docs.google.com/presentation/d/1PUvpXMBEDS45rd0wHu6t...
I think junior developers tend to invest in a single web framework and let their identities get tied up in the architecture of that framework.
UI through composition, building UI through assembling components from other components, has done away with those issues. The enforced encapsulation is frustrating that I agree is a trade off, but refactors become simple find and replace to point to new components instead of having to rewrite entire chunks of previously working code.
> UI through composition, building UI through assembling components from other components, has done away with those issues.
it should be noted, you can do this just fine in cocoa/uikit with delegation/message forwarding etc. but most people dont know about that imelots of subclassing and overriding is much harder to avoid with view controllers but view-level subclassing is usually an anti-pattern (if i got a dollar for every time i found a "RedButton" class id be a millionaire) but like most things people aren't either experienced or educated enough in these frameworks
> However, they constantly require refactoring as teams grow and systems become more complex. This leads to overly complex UI code over time that become brittle.
i think this becomes true with any system, but subclass-heavy code makes it definitely harder imo > ...is frustrating that I agree is a trade off, but refactors become simple find and replace to point to new components instead of having to rewrite entire chunks of previously working code.
if done well it is easier in swiftui for sure, but the way i see people write "in the real world" swiftui is used in a much more monolithic fashion and hard to pull-apart... (personally i love swiftui) but i think real-world usage will still he mudballs in a large portion of codebases (there is no silver bullet)At some point if the system guides everyone into doing it the wrong way, it's a problem with the wrong system. Subclassing is rarely the right solution, one of the things that's really refreshing about React is that most people tend to naturally avoid subclassing when using it.
It's the automagical rendering.
I am unable to reason about how even a fairly small react code base renders and updates itself.
In my own projects, I've had a lot more success with lit-html - which is basically the declarative view layer of react - and controlling the rendering myself, usually with simple observables.
Also helps to avoid the react anti-pattern of having your views full of state wrangling.
I encounter this in situations like: I want to open a drawer when an input is focused; the global state doesn't need to know about every input with a drawer, so useState on the component is useful. Already I've diverged from a global state. And I want something else to happen when the drawer opens (maybe an async network fetch, loading indicator, error messaging if the network fetch fails...), so I add useEffect, and now I'm adding side effects into the mix, and it becomes very difficult to reason about how the component got into its current configuration at any given time.
At work I have these components that I imagine will start small, that tie into some global state, but end up needing to keep their own internal state that grows and grows, and I have useEffects all over the place watching for other results of side effects... it's a gigantic mess. I don't know what the solution is. UIs are hard
In Vue, I'll usually create a service to handle local-yet-shared state (which is just Vanilla JS, no Vue constructs), or create a VueX module (which you could use in React, as well). It's much easier to follow than React's wrapper methods.
In my experience, in both React and Angular, a lot of the things I expect a framework to handle need to be managed by the developer (namely, keeping shared values in sync). Over time, patterns can deviate to where different components/modules use different patterns, and devs spend extra time reading through component files to figure out why their feature isn't updating as expected.
> the global state doesn't need to know about every input with a drawer
I like this example because it is exactly how it happens in real life every single time in my experience.
It does not need it, purely an aesthetic reason. Maybe it will perform worse if it does (maybe). If we commit to the model that we represent everything in global state (singleton) this problem disappears.
Let's say we keep some state for that drawer and pass it to the global state. Then we would keep a global state that is always current and an ELM-like model that is easy to understand (https://guide.elm-lang.org/architecture/)
For some reason that commitment is the first thing to drop, and usually not even for practical reasons, but for aesthetic ones or hypotheticals.
It seems to me it is this permanent fight between flexibility and correctness. If we want correctness we should stick IMO to a simple model (let's say ELM architecture, for example) and ruthlessly apply it, no exceptions.
If we want to use context, redux, local state, mobx, some direct DOM manipulation (as I see sometimes) then it is no wonder we cannot prove its correctness.
Most people find it difficult to accept constraints, even for their own good (type annotations, even using git). I still remember a project where I introduced git and after a few months of leaving an ex-colleague (still in touch) proudly announced that they got rid of it because it was slowing the team down.
"All of humanity's problems stem from man's inability to sit quietly in a room alone" — Pascal
The short summary is that React queues a render when you call some form of `setState()`, renders this component, and by default recursively renders all children inside this component too. Everything else is variations on that idea.
[0] https://blog.isquaredsoftware.com/2020/05/blogged-answers-a-...
Conal Elliot has been working on this since the 90s (e.g. http://conal.net/fran ), but has since rebranded it as "denotational design", since the FRP label now refers to more discrete, event-based systems like Elm and React.
Unfortunately, the API of early implementations required old states to be kept for unbounded amounts of time, which made them impractical; although newer implementations like FRPNow don't have that problem.
The thing that these approaches don't account for is the rendering aspect which should ideally be done on the GPU.
There's this duality between Array of Structs and Struct of Arrays [0]. People find programming with Array of Structs easier but GPUs work with Struct of Arrays. I think that a language is needed that fundamentally compiles AoS to SoA.
Another advantage is that repainting the whole scene is much cheaper do you can be a lot more aggressive with repainting everything.
ISPC does that.
>The application event loop coalesces these damage rectangles and initiates an optimized operation: it only redraws views whose bounds intersect the damaged region, and also passes the rectangle(s) to the drawRect:: method. (That's why it's called drawRect::).
So, according to this, you need an explicit run-time mechanism to optimize the interaction of parents with children, with some form of coalescing.
Antithesis:
>This is another reason why it's advantageous to have a stable hierarchy of stateful objects representing your UI. If you need more context, you just ask around. Ask your parent, ask your siblings, ask your children, they are all present. Again, no special magic needed.
...except here, where OP says you don't need any special magic to deal with parent/child relationships: just reach up/down/left/right and do your thing!
Synthesis:
The reason one-way data flow became so popular is exactly because the second view is a trap, or at least, a local maximum. If you are really doing complicated orchestration in your hierarchy, then you will end up reinventing the first wheel, to avoid expensive/inefficient parent/child/parent thrashing cascades.
React does in fact have a good solution for this, in the form of contexts. These also allow you to reach up and go talk to parents, in a controlled yet composable way. The way I describe them is "singletons but with scope". An underappreciated benefit is that you can extend a parent context and pass it down, replicating some of the benefits of inheritance, without the messyness of subclasses.
Where React falls short is that parents can't respond to children without re-rendering themselves, which ironically makes implementing e.g. nested tree widgets hard, even though the result is all tree-shaped.
Functional effect systems which can re-join after forking, and gather yielded values, do not have this issue, and I wish React would explore this avenue instead of the all the React 18 stuff they've been doing lately... it feels too much like they are leaning into the same Facebook "dumb read-only UI" style that the article correctly laments. They are straying away from React's original appeal, which was that it was "just the V in MVC", and instead becoming very opinionated on how server side and client side should be combined. Meanwhile the challenges of how to replicate complex legacy desktop UIs remain mostly unaddressed, with the official advice about event handlers, state and effects falling short by a mile.
http://weblog.raganwald.com/2006/10/are-we-blub-programmers....
If you're used to toolkits that give you a basically fixed set of components, in which creating new components is considered an advanced operation and there's no assistance with data binding, then something like React seems like a breath of fresh air. I've done a bit of JetPack Compose, and also some JavaFX and of course HTML5 stuff. On the web React is an upgrade simply because the DOM isn't meant for UI and HTML has no notion of components at all. On Android, well, the classical Android UI toolkit was never that great. It's a Java Swing era API with three different clock classes in it! I can't comment on UIKit, never used it.
Maybe a better comparison would be to something like JavaFX, which pre-dates the crazy for functional programming but benefited from the years of experience with classical toolkits like Swing/GTK etc. And here, it gets hard to really get excited by React. The blog post isn't wrong - the React model requires a ton of concepts, abstractions, and complicated infrastructures to try and recreate things that come for free in OOP toolkits. JavaFX supports data flow and binding because every property is both observable and bindable via lazy dataflow graphs. So your UI can indeed be a pure function of the model, but instead of re-execute/cache/memoize/diff, you assemble the computation graph for whatever needs to be reactive. Most of the time, you don't actually need to do anything complicated here and can write code as a straightforward imperative calculation.
Creating components is likewise pretty easy, albeit JavaFX is currently in a sorry state where the open source community around it doesn't maintain the documentation properly, so it's hard to link to a tutorial that demonstrates this. But basically you get a pay-as-you-go approach in which you can just group some widgets in a class, or you can be a bit more ambitious and inherit from Control which gives you things like proper focus/tab order management, the ability to control properties using CSS and so on.
When I read code written with JetPack Compose, the feeling it gives isn't really that great compared to the OOP style. The way it totally changes the core programming model of the language looks like an absolute nightmare to teach to new programmers. The most fundamental rules of the programming language are suddenly up for grabs - what looks like straight line imperative code actually isn't, variables might retain their state beyond the scope of a function call ... or might not ... and it seems like React/Compose codebases invariably degrade into tons of tiny functions passing giant amounts of stuff around on the stack, with lots of obscure performance problems that come from the game playing with the core execution model and all the diffing/patching going on behind the scenes.
In the end I find I agree with the author. Good UI is not in fact a pure function and the FP model is a poor fit. There is too much implicit state that is best encapsulated in the UI framework, and with an actually well designed OOP framework data binding just isn't painful enough to justify the costs.
https://stackoverflow.com/questions/22573494/react-js-input-...
Although if you model all the UI state, maybe you just end up with the DOM?
So smug that it's hard to take seriously.
Especially when even Apple is switching to SwiftUI, something that is the opposite of Cocoa and more similar to React.
Though I wonder how someone with both Cocoa and React experience looks at React and goes "Oh, it's the old-school Cocoa way of doing things!"
This blog post reminds me of HN four years ago when everyone had their little smug epithet about Javascript and web developers, those idiots who are too amateur to see the beauty of Cocoa and winforms or whatever most of us are happy to swap with something better.
> we’re adding a stateful function API as a preferred alternative to classes soon
Class components were the focus at the time, and are now all-but-deprecated. Also, Redux was still very popular in practice, which it isn't so much now (partly due to hooks)
That's a pretty big change in the way people use React, which certainly informs a discussion like this
Yes, hooks change the way we write React code in some ways, but in a lot of other ways nothing has changed. We still write components that accept props, have state, and return UI descriptions as JSX elements, and those components may cause side effects after a render is completed. Conceptually, the core principles of React are still exactly the same, and hooks didn't change that.
Additionally, Redux is still by far the most widely used state management tool for React apps. My rough estimates are that 45-50% of React apps use Redux, whereas Mobx and XState are around 10-15%.
I'll agree that Redux is not as "popular" as it once was, which is due to a number of factors. It was heavily overused early on, and the ecosystem has expanded to include a lot of other great tools that overlap with some of the use cases for Redux. But, "modern Redux" with Redux Toolkit is much easier to learn and use than the legacy hand-written patterns, and we get highly positive feedback on a daily basis from folks who tell us they enjoy using RTK. (In fact, RTK by itself has more downloads than Mobx, XState, or React Query.) So, that tells me Redux will continue to be widely used for a long time.
Curious how you arrive at these estimates? I would have thought fewer than 30% of React apps started in the last year or so use Redux, but of course, many still do, perhaps a higher percentage of apps that were built >2 years ago do (you could argue these are more mature, so they've "grown into" redux, though you could also say they're legacy and preceded newer React capabilities and tooling)
I don't have a strong inclination one way or the other, and have been toying with introducing Redux (or some other kind of state management) for the app I work with, but my understanding from the general sentiment of the threads/projects I follow is that market share of Redux has fallen in the last year or 2.
The really short answer is: mostly looking at NPM download stats, Github "depended by" numbers, and random polls on Twitter.
Which are all _horribly_ flawed metrics, but they're also all we have to go by.
I wrote a couple longer comments on Reddit a while back that went into more details on some of the numbers and the potential flaws in using them:
- https://www.reddit.com/r/reactjs/comments/lcgqnd/state_manag...
- https://www.reddit.com/r/reactjs/comments/skbyb1/the_most_po...
and unfortunately you asking me about this is tempting me to turn those comments into a blog post with some additional thoughts :) (I.... may actually try to do that tonight or tomorrow. If you're interested, keep an eye on my blog at https://blog.isquaredsoftware.com .)
I'll definitely agree that Redux usage has peaked in _relative_ terms, although as you can see from the download numbers it seems to still be growing in _absolute_ terms. Also it's entirely possible that fewer new projects are choosing Redux.
Then again, how do we even count "usage" in the first place? I've seen Web3 app boilerplate repos that include Redux Toolkit. If 1000 people clone that repo and play with it, how do we compare that usage conceptually vs one app using Mobx that's been around for years and has a bunch of developers working on it daily?
As I've pointed out in a number of podcasts and articles: I'm not trying to convince people they _must_ use Redux, or even that they _should_ use Redux. I just want people to be aware that modern Redux is way easier than legacy Redux, that Redux _is_ still widely used and is a viable choice, and what some of the tradeoffs are when using Redux or any other state management library.
I've actually been trying to get the community to come together and work on a centralized site that would list tools in different use cases and categories such as state management, styling, data fetching, and build tooling, describe purpose / use cases / tradeoffs for each tool, and have that as a recognized resource for people to use when researching what to use for a project. You can see the original RFC discussion and prototype site here:
- https://github.com/markerikson/react-community-tools-practic...
- https://react-community-tools-practices-cheatsheet.netlify.a...
Sadly I haven't had time to push this forward, and it needs to have more people involved and helping fill out content on the various topics (not just me).
https://blog.isquaredsoftware.com/2022/07/npm-package-market...
The biggest takeaway here is that based on these numbers, I'm actually going to have to revise my "45-50%" estimate that I've been throwing around for the last couple years down to about "33%". React downloads have continued to go through the roof, and they've finally separated more of a gap from React-Redux downloads. There's also a surprisingly large differential in terms of Github "dependent repo" numbers.
That said, Redux is most definitely still the most widely used state management lib by a mile.
My main guesses for the changes are that more folks _are_ just using React state and no separate state library, and possibly some influence from number of learner repos.
Anyone judging Redux differently if it has a 15% or 45% market share is making decisions based on the wrong parameters anyway.
Well, that's hardly a counter argument. The core argument should be whether "SwiftUI is better than Cocoa", and not whether a Big Tech company is switching to it unless we are in a popularity contest.
I mean, even Vue takes its name from that (pronounced "view").
https://folk.universitetetioslo.no/trygver/themes/mvc/mvc-in...
[1] http://fluxxor.com/what-is-flux.html
EDIT: I lied, React came first. Still, they have a lot of similarities, being developed by the same company.
https://blog.metaobject.com/2015/04/model-widget-controller-...
However, sufficiently MVC for the purposes of the post.
FWIW, this isn't actually the case.
React was first announced in 2013:
- https://en.wikipedia.org/wiki/React_(JavaScript_library)
The "Flux Architecture" was first announced a year later, in 2014:
- https://youtu.be/nYkdrAPrdcw
React's original influences were things like Facebook's internal PHP-based UI definition layers:
https://reactjs.org/blog/2016/09/28/our-first-50000-stars.ht...
UIKit is very mature and has evolved to a really good UI platform. SwiftUI is not even close to unseat it. Maybe in few years it will mature as well, but for now UIKit is the way to go.
As if it wasn't difficult enough to wrap your head around learning it in the first place, running into bugs makes it even harder because you think you're doing something wrong until you finally ask online and get told by people more knowledgeable than you, "I don't know why that's happening, wrap your view in a container and it'll work"
[1] https://youtube.com/playlist?list=PLpGHT1n4-mAsxuRxVPv7kj4-d...
So far its been great to build UI and animations with. Each release gives SwiftUI more apis and features, so there are less and less older style apis to wrap in SwiftUI ourselves.
And while you can't do everything in SwiftUI, it's pretty solid and capable now. I only have a couple things using AppKit in a large macOS project.
https://futureofcoding.org/episodes/011
17:30
"The core idea with react, and this is the only thing that matters, so don't view components as a react innovation. Components have been around forever. You build any sort of native application on Windows or macOS or iOS and there's a notion of component, some call it a view or whatever, but the idea of composing components out of other components has been around since the dawn of time.
I don't know why we weren't doing it on the web. I think we were just, I don't know, being stubborn or something. But that's not a new innovation."
Hmm...sounds just a bit like what they were trying to achieve was something along the lines of "Cocoa for the Web".
But what does he know?
¯\_(ツ)_/¯
Anyway, he does go on to say that the core innovation is having the UI be a pure function of some state. But that's the part that isn't actually true. It ain't a pure function. See Dan Abramov's comment:
Support for local state and side effects is absolutely a core feature of React components and not something we avoid for “purity”.
So if it's not a "pure function" of the state, then it's some mapping of the state. All UI is some sort of mapping of the state, otherwise it's not really a UI.
Hmm...
So being a "pure function" of the state is not the innovation, because it isn't true, and being some mapping of the state is also not the innovation, because all UI is a mapping of the state.
Hmm...
So what is the actual innovation? It is more or less directly and visibly expressing the UI in code. And since all our languages are essentially procedural (functional, OO) that means expressing the UI as a procedure (function/method).
And so the "pure function of the state" turns out not to be a feature of this model, but a (squishy) requirement. Because in order to make the UI definition a procedure, you have to re-run that procedure at arbitrary times (and ideally also run it partially). And so the requirement is "sufficiently pure that we can re-run it".
And that is an innovation, and it's kinda cool. But it does break down rather quickly, which is why all these frameworks keep iterating, and iterating, and iterating.
I understand 'functional' to be used as the direct contrast to 'procedural'! Is that not your understanding?
> So what is the actual innovation? It is more or less directly and visibly expressing the UI in code.
The 'visibly' part here doesn't really actually hold true, does it? Once you've componentized your <swiftui/react/html/[VFL](https://developer.apple.com/library/archive/documentation/Us...>, it's probably not super visibly understandable.
The best definition i can think of for declarative UI frameworks is probably something closer to 'frameworks that optimize for your ability to make a pure function representing state'.
(After all `[[UIViewController alloc] init]` does indeed purely say 'you have view controller' — that's just not super granular!)
In this light, isn't SwiftUI just a setup more optimized in this direction
Of course if a table (any collection really) contains differently looking items, it may have more than 10 cells, and rendering controller may choose between them based on which row/column is rendered.
React mentions in their docs a plugin which simulates exactly that (forgot the name, something like react-dynamic-scroll).
Also, some frameworks use cells to render active elements basics, e.g. an input without a frame, or a check mark cell without a background. This helps to make controls editable without instatiating a real input/check/button element at the coordinates of a cell. This makes every button in a container a single button which signals clicks to its container, which based on x,y knows which item that is and signals rendering controller that item X was “clicked on the button B”.
Click on the links, there are live examples.
> Hmm...sounds just a bit like what they were trying to achieve was something along the lines of "Cocoa for the Web".
More like native UI for the web? I'd take your point if he only mentioned macOS or iOS. Check your bias!
I’ve heard that the original React was built in SML, rewritten in OCaml, and later transcribed to JS (and now is developed in ReasonML)[1].
We shouldn’t downplay the unmitigated[2] disaster of language design that JavaScript (and more broadly, the engineering disaster that dynamic typing) is.
Just the fact that React was/is created by a person who is functional, static, strongly typed language aficionado is a testament that good things in the JS world comes simply because of its entrenched status due to being the only directly supported language in browsers — not because of anything inherently good about JS.
[1] https://news.ycombinator.com/item?id=15209814
[2] Now partially mitigated by TypeScript.