Not everything is a component, so why then is everything a component?
But as many have learned, going all in on React or any other framework leads to component soup, the modern equivalent of jQuery spaghetti. I recently attempted to spoon out a small portion of a large React app and move it to a lazy-loaded micro-frontend (not a fan of that architecture, but that was the task) and I couldn't. There were too many components with far too many imports all interdependent on each other. Here's a visual of what this small component and its dependencies look like (the two nodes circled in red are the basis for the component):
And to be clear, that's not the app. It's a component with its dependencies. To the user, it's just a simple page with a few charts and other minor bits of content.
It ended up being more practical to start fresh and write the code from scratch. That page will eventually become a single 100% vanilla dependency-free HTML file. It will be 30x faster and drastically easier to maintain because once I reduced everything down to UI elements there was no longer a need for framework-dependent product components.
So, to avoid hammering on every bit of UI with a framework, try making these distinctions when defining and building your components.
UI elements are what actually make up the user interface. They are the visual elements on your page that users see and interact with. They are the HTML. Here's some examples:
|UI Elements||Not UI Elements|
|text editor||admin page|
People see and interact with buttons and tables; they do not see or interact with abstract components like
QueryClientProvider. And they also don't technically see or interact with more concrete components like a dashboard or a news feed - they see the UI elements controlled by them. Do you see the difference?
And UI elements aren't just the native HTML elements. They include patterns of elements, like four child divs with a parent set to
display: grid making a 2x2 responsive layout. They are also higher-level elements like tabs, a sidebar, or a full-on text editor. The Custom Elements API has made such elements possible for many years now.
Regardless of programming language, framework, architecture, build pipeline, or device type, UI elements are always going to ultimately become HTML elements in the DOM 100% of the time. There are no exceptions to this rule because that's how browsers work.
Why then do teams willfully abstract them away into framework-dependent components? It's not easier, faster, more accessible, or more performant. It's because that's what they've been taught to do by framework creators and other influential developers. Influencers have their favorite hammer ready to pound nails, so they teach hammer and nails and not much else.
These are abstractions. They often, but not always, benefit from a framework. Their purpose is to bring logic, data, and UI elements together into a meaningful piece of the app. They import dependencies and encapsulate business logic. They manage app state. They provide structure and organization as the app grows in complexity. They're glue. Here's some examples:
|Product Components||Not Product Components|
|admin page||text editor|
The requirements for these components are such that vanilla just doesn't quite have enough. Patterns alone, like Model-View-Presenter, can do much, but there's often still a need for specialized mechanisms to structure and package lots of code. This is one reason a product component would need a framework.
attributeChangedCallback. Product components, on the other hand, are always internal or root nodes and are managing state and rendering in a way UI elements aren't.
The more leaf nodes, or UI elements, you have, the fewer abstractions and layers are needed and the application becomes much simpler overall. A project then has three clean layers:
And the product components go from complicated interdependent graphs like the screenshot at the beginning of the article, to a very clean tree like this:
At times it is necessary to nest product components. I have found there is never a need to go beyond three components - the App, the Page, and sometimes a section of a page. With UI elements I have never needed a fourth and often only need two. There is no need to incur the costs of the excessive "pyramid of doom" designs so common in React projects.
Well, that's UI elements vs. product components. Do you make a similar distinction? What's worked well for you?