Does React really violate Separation of Concern by putting HTML and JS in a single file?
Discussion started by someone anonymous
107 votes · Closed
Some explanation on this will be really useful for me and others. If yes - How? If no - How?
3.4K+ developers have started their personal blogs on Hashnode in the last one month.
Write in Markdown · Publish articles on custom domain · Gain readership on day zero · Automatic GitHub backup and more
Warning, this is going to be long...you asked for it...
Answering this question well requires looking at React from a couple of different perspectives. It also requires understanding a bit of the 35+ year history of presentation patterns as well as an understanding of web technology's purposes and intents.
First, it's important to understand that Separated Presentation patterns emerged mostly in the context of creating component models on various platforms. For example, MVC originated in Smalltalk, Supervising Controller and Passive View have their origins in things like Java Swing and Windows Forms, and Presentation Model and Model-View-ViewModel have their origins in binding-based technologies like Xaml, Flash/Flex and modern Web frameworks. Components can be complex and engineers found that it was better to define distinct roles and responsibilities within a component. Take the classic MVC pattern. The roles and responsibilities of a Controller are different from those of a View. The role of the Model is different from either a Controller or a View. Yes, these all may be part of the same component, but they have different roles and responsibilities within that component. They are concerned with different aspects of the component's "life".
Note: I'm using SoC and SRP pretty interchangeably here. This isn't something you can/should always do in conversation. I'm taking this liberty because you will observe that, if you "zoom in" to a specific implementation detail of a system, SoC and SRP are actually talking about the same thing. That's not true if you "zoom out" to look at the bigger picture of a given system.
What I'm getting at here is two things primarily:
- JSX, as a unique view language, isn't an SoC/SRP problem.
- BUT, developers often introduce the problem with how they use JSX to build components and applications.
So far I'm looking at this question from the perspective of design patterns and Uncle Bob's SOLID, but that isn't the only way to look at it. You can (and should) look at it in terms of web technology purposes and intents.
Some people think that HTML is about rendering. It isn't. A brief review:
- HTML - Semantic Content
- CSS - Presentation (rendering)
Developers I've interacted with, particularly those with extensive server-side or native UI toolkit experience, often get confused about the distinction between Semantic Conent and Presentation. It's no small distinction though. In fact, to hearken back to the previous section, you might think of it like this:
- HTML - Model
- CSS - View
Interesting isn't it? Hopefully, that makes more clear the importance of the distinctions in the web programming model.
There is a whole group of professionals in our community that care intensely about these distinctions. They are the Information Architects, UI/UX Designers, Web Designers, Graphic Designers, Marketing Specialists and Accessibility Experts. Note that these people aren't necessarily the same type of "developer" that is likely to have read Uncle Bob. They might not even think of themselves as a developer at all, yet they are an integral part of our community and the web ecosystem (more important than most developers feel comfortable admitting).
Summarizing this perspective:
Ok, we've covered two important perspectives. But, there's another important thing to look at, which I hinted at in the previous section: collaboration.
Most people think that OOP, SOLID and various design patterns have a primary purpose of enabling code reuse. They can help with that. People often also recognize that these things can improve maintainability or extensibility of a system. That's true as well. But more often than not, people forget that one of the primary purposes for SOLID, OOP and many design and architectural patterns is to enable team collaboration.
When you properly separate concerns, you can have more people working in parallel on a given feature. A component model that has a solid separation of concerns can enable greater collaboration between developers, designers, UX experts, etc. They can work at the same time on the same component. At the present time, it's not sufficient always to simply separate these concerns, but keep them in the same file. Because of the way that modern code editors work and the way that version control systems work, it's much better to separate them into different files. Not doing this creates a technical barrier to productive collaboration. Your team will be slower and your development will cost you more money.
The main point I'm making is that how you go about handling SoC/SRP technically, has serious non-technical side-effects, including helping/hindering parallelization of effort.
Ok, let's step back and summarize the whole thing.
- NO, because JSX is a view language. That's one responsibility.
The UX/UI Designer Perspective
- YES, because JSX mixes Semantic Content (Model) with Behavior (Controller)
The Team Perspective
- NO, if both...
- Separate files are used for the View (JSX) and ViewModel (JS).
- Either there aren't UI/UX/Designers involved, or they are productive working directly with JSX (not very common).
- YES, if either...
- Everything is in the same file, causing problems for version control or productive use of modern editors.
Now, a quick bit of followup to address other comments here:
- Browsers are used to render graphical elements...
- Remember that browsers aren't the only user agents for HTML. HTML is important and meaningful irrespective of any rendering.
- Separating HTML and JS is separating technologies. It is not separation of concerns.
- If they have the same concern, then why are two completely different technologies required? Do they do the same thing? No. This is an issue of "zoom" as I mentioned above. Components themselves, internally, have different parts that serve different roles. They are concerned with different aspects of the component's life. Separating them allows experts to collaborate better (among other things).
- JS is concerned with HTML, and they are inextricably linked.
- ...React takes that to the next logical step - linking state, lifecycles, and all view logic with the small, specific, manageable chunks of "DOM" and composing those as necessary.
- You just listed a lot of different responsibilities there.
Now, to the real point. Why is the author of this question asking it? There are a lot of possible reasons. Let's assume that they are honestly trying to decide if they should use React and have some honest questions/concerns.
If you are trying to decide...personally, I would tell you to avoid React. There are a lot of reasons for that which go beyond the scope of your specific question. But, let's look at it from the perspective of your question:
- Technically, JSX is a View language (SRP) +1
- Teams using React could suffer productivity loss depending on their development habits (lack of vigilant adherance to their own SoC architecture) and team makeup (presence of non-JS-experts; though possibly more experienced than anyone in other technologies). +0 (benefit of the doubt)
Even if I try to be conservative with respect to what I know from experience happens in the real world, it comes out negative. For me, not considering any other issues React has, this is just too much risk and too much exclusion of potential talent and creativity.
No. Let's talk about browsers first. Browsers are used to render graphical elements like rects, circles, fonts, and some other shapes. In order to describe the stuffs we want to render we need to write code. There are mainly two ways in which you can tell a browser what to do:
- write in HTML, a text file of tags and contents
- write in DOM API, like
Here's a thing. User interfaces always requires lots of code and we will need abstractions for that. In HTML, people use nested tags, in DOM API, it's
Element.appendChild for example.
In the early days template engines are widely used. And in EJS there's
include to reusing small pieces of templates. It's very handy on HTML side, while creating UI in DOM API is slow and imperative. So, abstractions wins.
Here is another explanation of what I mean
This comes up at work a bit with the React skeptics. I like the way @vasan put it - separating HTML and JS is separation of technologies, not separation of concern. The JS we write in the browser is there because we need to dynamically interact with the DOM. JS is concerned with HTML, and they are inextricably linked. I see something like templates as an intermediary, linking small chunks of HTML with data, whereas React takes that to the next logical step - linking state, lifecycles, and all view logic with the small, specific, manageable chunks of "DOM" and composing those as necessary. I personally love JSX because we can write views in a way that is much easier to reason about than
document.createElement("x"), you just create the element:
This was not an inevitable or even an ideal outcome. It was an unfortunate historical accident. React just puts the two 'concerns' together in a way that feels natural and minimises pointless friction in practice.
In simple apps this might not seem like a big deal, especially when starting out.
You are for all intents and purposes very close to writing client side PHP. Or Perl, both of which allow you to mix and mingle.
As your projects get bigger, you hopefully are using modules and life is still pretty perky. But at some point the person who has to deal with the html fragment will need to be someone proficient only with HTML, and they won't know what they are looking at. Or worse, you will find out that you now own a very crazy mixture of HTML and CSS written by someone who went a little off the deep end mingling.
I think there are already long answers. I'll keep mine short.
React does not put HTML and JS in a single file. There is no HTML in React, JSX is no HTML, it makes look like HTML (virtual) DOM elements creation. HTML is a markup language to represent a DOM (or portions of). React components output (virtual) DOM elements, and don't need HTML.
You can fail to have separation of concern in React, by putting together (without structure) logic for: getting data, keeping hold of it, updating it, representing it.
React ecosystem came with Flux and Redux. You can also look at Elm's Model-Update-View pattern, Cycle's Model-View-Intent pattern, the State-Action-Model pattern (SAM).