Does React really violate Separation of Concern by putting HTML and JS in a single file?






107 votes · Closed

Some explanation on this will be really useful for me and others. If yes - How? If no - How?

Start a personal dev blog on your domain for free and grow your readership.

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

Rob Eisenberg's photo

Warning, this is going to be 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.

With that in mind, let's look at JSX first. What is the purpose of JSX? Does it have one or many? My understanding is that it's designed to serve the View role. To really understand this, you must see JSX as neither HTML nor JavaScript. You must see it as a unique View language. So, from the perspective of separated presentation, it seems to do a very good job, namely fulfilling only one role, that of the View.

That's the idea, but is that the reality? If you look out and see how developers are using JSX in practice, are they using it as a View language? My guess is that while JSX is intended to be a View language, it is probably most often being used as JavaScript with embedded HTML (this is what I've seen in most demos/presentations/samples/tutorials). This way of thinking of JSX can lead a developer to mix concerns. It's quite possible that the React component model may even encourage this since the same class controls state and renders it. I think the cleanest way to use React would probably be to treat the component class as a pure JavaScript ViewModel and to extract the JSX rendering logic into it's own class/object/function, which serves as the View for the component.

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)
  • JavaScript - Behavior

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
  • JavaScript - Controller

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).

So, when you show JSX to a person with one of these backgrounds or areas of expertise and ask them "Does React violate separation of concerns by putting HTML and JavaScript in the same file?" They are going to say YES.

Someone who is tasked with the job of properly authoring Semantic Content is going to really have a problem with JavaScript getting in the way. A UI/UX engineer who is working with design tools like Sketch or Illustrator is going to be disturbed by the fact they can't write plain HTML and CSS. A designer or artist who wants to control rendering details and has to weed through JavaScript to find the proper HTML structures to apply CSS to isn't going to be happy.

The effect of JSX on this segment of creative individuals is to basically exclude them from the web. It nullifies their tools and renders anyone without extensive JavaScript capablities unable to create semantic content. That's a pretty serious problem. Most of these individuals could tell the average developer a thousand things they were doing wrong with their HTML and CSS because they are experts in these areas. Yet, the overreaching of JavaScript into the domain of HTML, makes it difficult or impossible for many of these individuals to collaborate or create - certainly not on the level of expertese that they actually hold.

Summarizing this perspective:

  • HTML, JavaScript and CSS have different roles and responsibilities.
  • Overly mixing roles can exclude a huge segment of the community from participating because they are masters of particular roles, often times not the one associated with JavaScript.

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.

Does React violate separation of concerns by putting HTML and JavaScript in the same file?

The technical JavaScript Developer Perspective

  • NO, because JSX is a view language. That's one responsibility.
  • BUT, this implies that the JS developer is self-enforcing SoC/SRP on his own architecture by not mixing ViewModel concerns in his JSX. This type of vigilance "in the wild" is highly suspect because JSX involves the full JavaScript dialect.

The UX/UI Designer Perspective

  • YES, because JSX mixes Semantic Content (Model) with Behavior (Controller)
  • YES, because the intrusion, specifically of JavaScript, into the Semantic Model makes it difficult or impossible for me to play my role and leverage my expertese and skills.

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.
    • Members of the team who are comfortable with HTML/CSS but less capable with JavaScript are excluded because of mixture or roles.

Now, a quick bit of followup to address other comments here:

  • HTML, CSS, and JavaScript all have the same concern, to render a view.
    • HTML is not about rendering, it's about Semantic Content. CSS is about rendering. CSS literally "binds" the semantic model to a set of rendering instructions via selectors. JavaScript is about behavior. It is only truly about rendering when not using HTML semantically or when working with a Canvas.
  • 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.
    • I don't think you mean that. I'm sure you can think of lots of things to do with JavaScript that don't involve HTML, as well as lots of things with HTML which don't involve JavaScript.
  • ...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
  • It is easy for developers to mix concerns in a JSX file because the format uses JavaScript and HTML and most developers either aren't vigilant enough to stick to a solid architecture or aren't experienced enough to see where they are going wrong. +0 (benefit of the doubt)
  • JSX allows JavaScript to encroach on Semantic Content extensively, making content more difficult to author and read than plain HTML. -1
  • Those less comfortable with JavaScript, though they may be world leading experts in UI/UX/Etc. are now no longer able to participate in application or component development, or are severely stunted. -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.

Show +14 replies
Kaan Özcan's photo

@EisenbergEffect const HelloMessage = (props) => <div>Hello {}</div>; Here is your example. There is nothing confusing about this way of using and you can adopt similar way of style all around the application and you should. It's much more better option then %99 of other frameworks and much more simpler then all. It's only bad choice when there are no Javascript Engineers in company...

Rob Eisenberg's photo

@knozcan Thank you for the example. I'm not sure if you read my post now though. What you show here is exactly what I recommended developers do when I said "I think the cleanest way to use React would probably be to treat the component class as a pure JavaScript ViewModel and to extract the JSX rendering logic into it's own class/object/function, which serves as the View for the component." When you do that, that solves a lot of issues but I have never seen a single React presentation/demo/sample that actually did this. If this is the right way to do things, then I hope the React community starts showing that a bit more. That said, the JSX you show is a simplest possible example. If you have any sort of list rendering or conditional rendering, you are going to be changing that a lot and there will be a lot more JavaScript involved. The person who needs to work with HTML won't be able to avoid that. As I said in my post, if you have a designer that is comfortable with that as a View language, it's fine, provided the above practices are still followed. However, that is not, generally speaking, something that the design community and other web creatives are comfortable with based on my experience and research.

Vasan Subramanian's photo

Separating HTML and JS is separating technologies. It is not separation of concerns.

Jon's photo

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 document.createElement and Element.appendChild

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.

And React simply introduces a way to created DOM directly with JavaScript data structures rather than plain HTML tags. JSX is a syntax sugar(which personally I don't like).

I think putting HTML and JavaScript into different files is more like a habit. In React, yes they are put in the same file. But it's doesn't matter. One can still separate DOM code from logics. MVC is still working if you want.

Actually I think React is doing "separation of concerns" better than template engines. In Views rendered by HTML, one has to use jQuery or something to bind events and update DOM nodes. JavaScript code is thus heavily dependent on DOM structure. It's not always easy to maintain code like that.

Joshua Barker's photo

Whatever React's ivory tower ideal may be, the reality is that developers by nature are lazy and are always looking to take short-cuts. In the 13 years I've been programming, across 20+ projects, what I see again and again is that as a project ages, the tendency is to cram more and more junk into gigantic files that are impossible to follow or debug. To me, JSX smacks of yet another "short-cut" that hard-core "coders" like, because they tend to eschew Business Driven Development paradigms and only think in terms of short-term gains (e.g. I get to keep my markup in the same file as my JavaScript... Now I don't have to have two files open at the same time... yay!!!). In reality, what always ends up happening is that you move-on, and someone else is left trying to figure out what the hell is happening in your 10,000 line monster.

Michael Bradley's photo

No. React is a view layer. HTML, CSS, and JavaScript all have the same concern, to render a view. They are different technologies sharing the same concern in this case. I like that the view and rendering logic are in the same file. It's really all just JavaScript anyway, JSX is not HTML and get's transpiled by React into plain old JavaScript functions.

Here is another explanation of what I mean

Will Cameron's photo

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: <x>{composable}</x>.

Dan Shappir's photo

Separation of concerns, no. React components encapsulate both presentation (HTML/CSS) and behavior (JavaScript). It does potentially violate separation of responsibilities, because JavaScript is written by devs, and HTML is often written by designers. Putting them together limits the ability of designers to modify the HTML.

Daron Robinson's photo

In the context of the browser, JS and HTML are joined at the hip through the DOM. This whole SoC debate is merely a side effect of the fact that HTML was conceived as a static layout language, an extension of passive document markup languages like SGML. Javascript was only (hastily) added after the fact to increase utility and interactivity once it became plain that the web could be more than linked documents.

So Javascript was created to make up for deficiencies in the original vision of an HTML based web, and this is reflected in its DOM centric nature, it's mainly there to tweak the view and user experience, not to do arbitrary programming tasks or pure mathematics (sorry Node).

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.

Andre Lewis's photo

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.

Or even worse, now you have logic for rendering everywhere and it's a year later and you don't know how a particular fragment got generated since you assemble fragments by hand in the javascript in the html fragment, and well.

I mean seriously, how hard was it to separate out that JS in the first place? Not very. How much of your representation could have just been html fragments by themselves and easy for a designer to use? Not very. My personal ethos on the subject is remove as much of the code as possible, or use something like Mustache to control flow, and make it very simple for a designer to be a designer, rather than require them to be proficient in Javascript as well. That being said I think @EisenbergEffect explained the situation very well.

Jiri Spac's photo

No because HTML and JS should not be your primary concerns in a frontend app. How do you split your app into a set of simple and reusable components-that should be your primary concern.

Thomas Roch's photo

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.

The way React and friends work is dictated by functional programming. Data is transformed by JavaScript to DOM elements, there is no HTML. I wrote an article about this:

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).

Nico Hoogervorst's photo

FYI: You can use Wix React templates to achieve a better separation of HTML and javascript. Examples: This makes it easier to find and correct HTML fragments in a big project.