4 ms·
I like JSX a lot. The idea of reusable stateless components is totally on the right track. The latter is what I really liked about the early versions of React,
by Chris_Newton 6y ago
I like JSX a lot. The idea of reusable stateless components is totally on the right track.
The latter is what I really liked about the early versions of React, back when it was seen as “the V in MVC”. The basic premise of having a declarative UI, so you only had to define what is rendered in terms of absolute state rather than relative transitions, was a good one. React’s virtual DOM mechanics made working that way reasonably efficient for most practical purposes. The rapid adoption in those early years is testament to how useful that combination of declarative+efficient really was.
However, I feel like as time has passed, the emphasis in the community has shifted towards trying to shove more and more that isn’t view logic into the React/JSX parts of their code, and that has caused all kinds of unnecessary problems.
At first it was as if, just because we had a tidy mechanism to write nested components easily using JSX, every little aspect of application behaviour was now supposed to be implemented as a component and shoved into the tree. This led to patterns like higher order components, and thence to more patterns trying to manage the added complexity introduced by having lots of non-rendering components wrapping everything. By this time, the inmates had taken over the asylum and any pretence of React being used primarily as a clean, declarative UI tool had been all but forgotten.
The idea of managing application state separately and systematically was old long before React came along. Relational databases and ACID transactions had been a cornerstone of software architecture for decades by then, as had the idea of having a separate data model to hold and systematically update application state within desktop software. The early React community was clearly aware of these ideas as well, not just from the “V in MVC” description but also the idea of Flux and before long the Redux ecosystem. And yet, developers still often seemed to keep their application state within their React components instead, which predictably led to all the same problems that had once caused traditional GUIs to move away from retained mode and towards separate state management and immediate mode rendering in the first place. This in turn has led to interest from the React community in ideas like context, and today along with hooks we often see talk of replacing tools like Redux with React Context instead.
It’s not just application state, either. We’ve seen more and more responsibilities pushed into React components over time. It doesn’t seem unusual to have those React components even dealing with communications to transfer state between the browser and the server now, along with all of the awkward mechanics like async fetching from APIs and cache management.
Most recently, the talk is all about how great hooks are, because they let you consolidate or remove of lots of awkward logic that used to be spread through different lifecycle methods in class components. Sometimes, as with this article, the idea gets taken to an extreme. But I can’t help wondering how often anyone stops to ask whether 99% of that logic should ever have been tangled up with the rendering code of the application in the first place. Aren’t we in danger of regressing to big-ball-of-mud antipatterns, just using a big-tree-of-components instead this time around? How do you even test an application properly at scale if you’re forever tangling up your rendering logic, state management, client-server communications and who knows what else, and then obscuring much of it inside React components that end up being tightly coupled because they rely on a certain hierarchy to set everything up just right?
React itself still seems like a useful tool for the same reasons as always, and functional components are a nice incremental improvement on the boilerplate that came with class components in the early days. But the grumpy old man in me can’t help feeling that a lot of the other “progress” in the React ecosystem has been more a series of missteps taken because those who don’t study history are doomed to repeat it. There is still a lot to be said today for using React as a nice, clean, reasonably efficient rendering library for your UI, and for keeping other concerns like state management and network communications separate and using the right tools for each job.
- richeyryan 6y agoI think a lot of what you're saying is very true. Its been said before that the React and SPA community in general has had the pleasure of rediscovering past concepts as the community has evolved. I suspect in a couple of years handling application state in your view layer, even using their native capabilities like Context in React or Vuex in Vue will be viewed as an anti-pattern. As I said in another comment. Effector is something that interests me as it seems to hit a lot of right ideas in terms of reactivity outside the view layer. It can hook into React with hooks or Vue with the Composition API. Hell its stores just work natively with Svelte. This brings us onto the most interesting point. Virtual DOM libraries aren't necessarily the only/best solution. Compiled solutions like Svelte and SolidJS are offering alternatives that address some of the size and performance concerns that VDOM libraries raise. If your state management is tied into that whole ecosystem, you have to throw all that away to benefit for advancements in the view layer. This is to say nothing of the fact that even sharing code between React and React Native is difficult to do easily. Whether Effector is the answer I don't know, but I believe it has the right ideas (it is inspired by the likes of Reframe and Flux). Something else might come along that is similar but presented better. However I could totally see a movement that espouses developing your apps data first and then wiring in your UI layer later. Maybe it would even have a TDD or repl based approach. Unfortunately I think it would ultimately be at odds with the beginner friendly, just get something working perspective that a lot of libraries take. How to bring new starters along so they can follow and understand is a much bigger question
- Chris_Newton 6y agoThis brings us onto the most interesting point. Virtual DOM libraries aren't necessarily the only/best solution. That is surely true as well. Even a perfect implementation of a VDOM library is necessarily doing a lot of extra work compared to direct DOM updates if you already know exactly what needs changing. For a “typical” SPA, if there is such a thing, React’s virtual DOM system is fast enough to make its declarative UI strategy viable, which is enough to make it widely useful. However, it can still become a bottleneck given sufficiently demanding conditions. React without a lot of help can still choke quite easily if it’s asked to render something like a table with thousands of cells or an intricate SVG diagram that needs to animate smoothly. Giving React the help it needs typically means bypassing some of the diff logic one way or another, for example by providing sCU in a class-based component or a list of dependencies to hooks. However, these kinds of changes also introduce potential inconsistency between what you’d normally render and what gets rendered with a bypass in place, which creates an opportunity for bugs and seems to be fighting against the whole idea of declaring your UI once and then letting React worry about all the details of maintaining it.