But I've learned to like it. React encourages you to keep components very granular and small and so the amount of markup in each component doesn't really get in the way I find. I've also learned to appreciate how easy it is to reason about what React is going to spit out onto the page because the view is right next to the logic that dictates the various states of the view. Feels very concise.
I still don't like the idea of it, but in practice it works quite well.
You can replace JSX by hand-coding with React classes - take a look at the compiled jsx and mimic that. I find it as easy to work with, and less cognitive dissonance [ a personal preference ]
I actually am looking seriously at Mithril in preference to React for my next chunk of work.
I might swing the other way if React native became stellar [ and viably crossplatform ]
Q: which do you prefer - this:
ReactDOM.render(<div><p>Hello World</p></div>)
or this? ReactDOM.render(React.createElement("div", null,
React.createElement("p", null, "Hello World")
));
A: handlebars.A: mithril.js
But you never write HTML with JSX, that's the point. XML like syntax is just sugar that gets transformed into functions. This is not HTML. With angular you need to use string templates which cannot be easily validated by IDEs for instance. JSX syntax validation is straight forward because it's directly integrated in the language.
If you don't like mixing logic into HTML you're free to create dumb components that only contain as much logic as you would want to put in a template. Such a component would accept properties and output a representation of the resulting HTML. A smarter component that does not generate HTML will provide the logic required for the template to function. That approach actually encouraged and is the right way to do React.
The bonus of this whole generate-HTML-representation-with-functions thing is that you pass around native JS values instead of stringified values and magic strings. Want to provide an onClick callback? Pass a callback. Not some magic string that represents a key which holds the callback in some object defined by framework-specific convention. No, you just pass a raw javascript function that will be run on click.
This might seem like a trivial distinction, but it's the difference between writing native JS vs writing magic framework code. I vastly prefer the former.
(at least 1.x did)
At the end of the day you go one way or the other, my preference is the template not having the ability to affect logic as it is not natural to look thru templates to find what is mutating the state of your application. I liked Dojo and I think react is a step back in that direction which in my personal opinion is the right direction for large web application.
component = React.createFactory(MyReactComponentClass);
component(props, children);Edit response to person below (rate limit): there's no 'problem', just that mustache is still more familiar. Moving JSX into a different file doesn't change that.
So for example in case of parsed templates, to pass a callback to onClick you'd need to define a convention on how you're going to locate the callback by a given string (since you can't pass the function itself, you need to pass some "name" of that function). Whatever logic that will be, the result will not feel like React anymore because you're back to typical framework-specific template magic instead of using plain JS.
Putting behaviour in HTML is a bad idea. Leave it in JS, and have one place to go when the behaviour changes.
This is not what I'm doing. JSX is JS. I'm not putting any logic "in HTML". If I were able to express what I'm doing in mustache-style syntax, it would be:
Blah blah <a onclick="{{ callback }}">Click me</a> Blah
Where `callback` is a reference to a JS function (rather than a string holding it's name).What's your ideal way of registering an onclick callback?
* With React & ESLint you get basic checks to make sure you're not passing non-existent variables
* Your IDE understands what you're doing and lets you jump to callback definitions
* You understand what you're doing because you have one obvious place where you do templating and data binding.
* Your actual behaviour logic is still separated from your template, living in some other JS file.
On the other hand, if you add event listeners to HTML from JS the classic way, you get other problems:
* You're querying the DOM tree by CSS classes or some custom attributes. It's surely a familiar way of doing things, but also fragile and unintuitive.
* It requires your JS to know the structure of your DOM to some extent, and that structure is defined elsewhere. So it's basically the same problem as with mustache templates – passing around magic strings – but the other way around.
* Neither ESLint nor IDE will help you do it.
React mixes logic and structure, which causes no harm, because both are written and maintained by same developer.