Look at the new default "razor pages" web project for .NET core. While it it is a little bit fancier, it basically brings back the same mental model that PHP has been using for decades. That is, cram all of the logic into a single file, and use a "service locator" pattern (I know it's actually DI under the hood) to "inject" extra functionality. In this way it is easy to trace where all of the pieces are coming from. Why abstract your `UserRegistrationView` to accept any `UserRegistrationModel` from a `UserRegistrationController` in a "decoupled" manner when the reality is that only one of any of that actually needs to exist ever? Might as well have the orchestration right next to the use-case!
The above applies to (what I believe to be) a significant majority of use-cases. At least the interesting ones.
It’s ironic that this is done in the name of “Separation of concerns“ -
You know what separates concerns: having everything that affects this component - in one place. That’s true separation of concerns.
I’ve worked in multiple frameworks in multiple languages and nothing does it better than modern react (especially with webhooks).
For my own experience with things that were specifically MVC or MVVM:
In C#: Asp.net MVC, WPF (with/without Prism)
In Typescript: Knockout, Angular 2.0+ (I guess it wasn’t mvc really - I disliked it for other reasons)
React (with hooks) on the other hand is the embodiment of a pure Functional Programming UI.
I can literally write a component with a single import and a single function.
For every reason functional patterns beats OOP patterns, react beats mvc - and achieves true separation of concerns (feature aligned concerns).
Not really — unless React is the only library you use.. MVC is still the best pattern. If you are an iOS developer you may already be familiar with MVC in Cocoa. Most UI frameworks, including ASP.NET Core, JSP and JSF (Java based frameworks), Ruby on Rails, and Django (Python) are all based on MVC. That's no accident. These disparate platforms — mobile and Web — all converged on MVC because it is the best architectural pattern for developing user interfaces.
Even within the frontend world and not in React you have all sorts of new state systems and structures that are in my opinion far more intuitive, less code, less cross cutting concerns, easier to change and grow more naturally. The gist of it is either a global state store with cursors and namespaces (I like this less than most) or a global state system with state split out (see Recoil) or an entirely tree based reactive state system (see mobx-state-tree or mobx-store) or even just nesting reducers or any simple nesting state container (pure react, zustand). I’ve recently put together gqless[0] with a state system similar to recoil but simpler (sort of like use-atom). It’s wonderful.
Your data is a tree/graph, you app is a tree, your file system is a tree, everything matches. You just slot in state with corresponding actions and at the level of the view hierarchy where it first becomes relevant (router at top, view controllers are spread in the middle layers however needed, and leafs get their own state as needed). And all data level things stay up in the graph, which I guess you could argue is an M sitting above it all, the VC are blurred together with more C at the top of the tree and pure V at the leafs. Even styling is all encapsulated where it’s used. Each piece is a lego block that can be moved around. And yes, it works, and works well, even without all the handlebars of Rails.
Wouldn’t dream of going back. It’s perhaps not a mature enough ecosystem for most to navigate their way to getting a good DX on a stack like that. Many pieces have rough edges if you don’t know what to avoid, it’s not like these huge mature frameworks that keep you away from scary stuff but also box you into a rigid structure. But of course it means you can do all sorts of things unimaginable in MVC land.
In any case, my critique is not levied against MVC the pattern, rather, how it is manifest. One can logically follow MVC without the physical separation of concerns (files). It's a continuum: You start by defining your state, view, and orchestration all in the same place. Should any one piece of the above suddenly need to be reused elsewhere, you then abstract as necessary.
I was pushing back against the idea that "inlining" CSS/JS with HTML is poor practice. What React achieves, because it demands you inline JS (and CSS if you want) with the HTML, is a simple, declarative development paradigm. It's like reading a function. No procedural ad-hoc `let el = document.querySelector('#id')` garbage getting in the way. The behavior is with the component, not around the component. In many ways, this is how OOP was supposed to work.
The nitpicks you have on Twitter are on specific behaviors (video and jumping and slow fetch) that have nothing to do with React. The site itself is lightweight and runs fast.
Good React is fine for large applications, but not for websites. Even in applications a few lines of Javascript and a rendering backend can replace entire JS frameworks. Try disabling Javascript for a day and you can see how many pages just become a white screen because whatever is replacing the browser's renderer isn't loading.
> Twitter is a good example, great performance.
I agree that it's a great example, but it performs horribly for me. I use their website on my phone and videos rarely play back properly, content jumps around while navigating, empty screens and loading bars are everywhere. Sometime I just have to reload because the Twitter website decided it doesn't want to load images anymore. Nitter links, on the other hand, load instantly, including image and video content, because of its minimalist approach.
Server side rendering is a welcome improvement because it means the developer doesn't offload the website's calculations to their visitors. I'm fine with whatever framework people pick on the server, as long as my browser doesn't get its rendering engine replaced by the fancy framework for the week.