So we've seen a push toward components that mix technologies, but separate concerns. And it's been great.
People learnt that mixing behavior and presentation was bad but that was a specific case of a more general rule.
In fact - "separation of concerns" is itself a specific example of an even more general rule which is something like "Make code easy to reason about" or "reduce side-effects" or similar. It's hard to give advice that doesn't sound hand-wavy and empty without getting specific. But as soon as you get specific you exclude alternative solutions to the same core problem.
Programming is largely about managing complexity and there are many ways to achieve that. But learning how is a subtle art indeed.
The reason why we need software design principles is because software changes. Software design principles are methods of organising software that make it easier to implement changes.
When it comes to changes it seems that the golden rule that makes things easier for humans is: things that vary together should be together (and things that tend to vary separately should be separate). Its interesting to think about why this is the case, but I'll skip that and take it as an axiom.
There was an article (which I can't recall the URL of) that argued how all the SOLID principles stem from this basic rule.
Single responsibility principle: it follows directly from the above rule: A class should have only one reason to change (keep things that could change separately separate)
Open/closed principle: Interfaces should vary significantly less than their implementations, so that both producers and consumers of those interfaces can vary independently of each other. e.g. Shape can have a method draw that takes a canvas interface: now we can vary both the canvas implementation and the different shapes independently.
Interface segregation principle: don't put too many things in an interface, they might vary differently. Make separate interfaces based on consumer types since change in consumers are more likely to affect changes in the interfaces they use, and having one interface for two types of consumers means two separate sources of change that vary differently.
Map / filter vs for loops is simply this principle applied in the small. The code to initialize an empty data structure, iterate through all the elements applying a function and then store the resutls in the data structure is always the same. The only thing that changes is the function that defines the transformation. Since its a concept that is very common and never changes, it should be separated from the transformation itself (which changes often and depends on the problem domain) and be given a common name (map)
It then follows easily that separating the component template from the code that manages component state doesn't really help. Its fine in server-side languages where the template is simply the final function in the data transformation pipeline for that request, with multiple potential views on the same data (html, json, xml etc). However, on the client side most of our code manages changing state closely tied to the DOM based view: for example, the sort column and sort direction of a table, or the current item selection, etc. The kind of state we keep is directly tied with how we present things (sortable table? => sort column and sort order; expandable tree? => expanded/contracted state for all branches, etc). As our view/component requirements change, the state we keep for it (and the way we manage it) also changes.
And since things that vary together should be together...
In the long run, the SPA craze will backfire, big time. Rect components are not semantic and not declarative. There is no way to examine them without executing code. This is an elephant in the room most fronted developers willfully ignore right now.
If you can pin down your definition then I'd be able to provide a more concrete opinion.
> The notion of separation between information, presentation and behavior couldn't be any more fundamental.
Fundamental to whom? Outside of web development this separation was never fundamental - see the post above regarding "separation of concerns" - which is a much better candidate for a "fundamental principle"
Separating css, html, and js makes sense when you're writing a document, and the content is the html and the css is strictly formatting.
It makes less sense when you're writing an app, and the styling of the html is an integral part of what is being created. The javascript works the same way; it's often integral to what's being rendered, not just patchwork adding small amounts of functionality to an existing document.
But probably most importantly is that react gives you a different way of separating concerns: it's very easy to put different chunks of the UI into different components/files, so your app is divided by functionality, instead of divided by technology. Keeping the html (and sometimes css) with the js that uses it helps increase the cohesion of small units in your UI that intimately work with each other, while separating those from other js/html/css for other units.
Preferably, all local concerns of a component (not referring to the React component class but the abstract component: a single unit within a larger project) would be in one place. For the front end of a web app this includes structure, styling and behavior. So it makes sense to define the structure (HTML), styling (CSS) and basic behavior (animations, different states it can exist in, etc.) in one place.
React models this using JSX, inline CSS (or CSS loaders) and the React component API.
Now we have ways to use these patterns and still have them be maintainable, which means it's time to reevaluate that previous effort. Co-locating styling with structure and behaviour tends to make our lives easier.
I can go one step further, I work on a React-based website which achieves straight 'A's on webpagetest and scores 100 on Google Pagespeed (Mobile and Desktop), this took far less effort than it ever took me to achieve worse results on previous stacks.
The component model (with co-location of styles) is incredibly powerful, and it works, give it a try.
Styles work very well on the per-component level. The best and worst part of CSS is the "cascading" part.
The thing is that with React, you aren't really writing HTML. Sure, JSX makes it look like it, but it's not a template, it's actually just a Virtual DOM element tree. This means it doesn't have the same issues as many templates.
> logic buried in HTML that is hard to find and hard to reason about
That's a complete non-issue with React and much more an issue of the traditional way of breaking it up in different files which look separated but in reality are extremely entangled.
Also, regarding the CSS questions, setups like CSS Modules in a Webpack build make the CSS very maintainable. Not to say there aren't drawbacks, but IMO having the classes be dynamic makes everything way more flexible. And, tools like hot-module-reloading make front-end development so much more enjoyable.
Styling is syntactically really just markup decorators after all, although CSS may end up Turing complete if it isn't already :) (this is probably a bad thing)
JS is actual programming language an you can split out styles to separate style library without using .css files.
You could also split out render function (that uses JSX) or its parts to separate file. But you'd rather keep it close to logic that interacts with it and keep the whole component, logic plus presentation small enough to understand with a glance.
That on scale it's not easy solvable.
And that's the reason why we are looking for other approaches to isolate/share the main functionality.
This really scares me. We spent a lot of effort removing inline styling from HTML with CSS, and yet it still creeps into our HTML. We also have created a lot of <program language dejour> "template" languages (e.g. PHP, Python, ERB, etc.) mixed in with HTML, which also tends to end badly (logic buried in HTML that is hard to find and hard to reason about).
How does React solve the "everything mixed into HTML" problem? Are we going down the same path that ended badly last time?