Scala is the only other language I know of which has some kind of XML/HTML syntax support (scala.xml). (But it looks like it got removed. [2])
Scala is the only other language I know of which has some kind of XML/HTML syntax support (scala.xml). (But it looks like it got removed. [2])
This is a very common confusion because most people approach JSX via React, and as such never really grasp that JSX is a separate, independent thing. If you're interested in learning it standalone, I'd highly recommend working with either the Typescript `jsxFactory` compiler option, or the `@babel/plugin-transform-react-jsx`
The "opposite" approach being using a template language like the one in Svelte or Angular… or like PHP (or Velocity, or Jinja) (for me JSX is not a template syntax at all).
I think template languages are also prone to rendering / logic mix, I don't know what is an elegant solution to this problem apart from getting used to this reality. Maybe something like QML, using data models, instead of having a for loop to render lists for instance.
Yes. Which makes any issues the gp mentioned entirely up to the implementation of that function call.
> seems like everything the parent said could apply to any use of JSX, except for the attribute naming issue
If by "could apply", you mean anyone could write a function that has those issues, then yes I guess. My point was that if you want to avoid those, they're in no way inherent to JSX. Is that what you meant?
I mean, I guess "blurred line between rendering and code" is less about the function implementation, and more about project / file organisation choices (including conventions of a frontend view framework community), but it's still certainly not inherent.
> I think template languages are also prone to rendering / logic mix
True. I think you do need a lot of discipline if you want to keep a clear and consistent separation, and it's also not always worthwhile (there's a codebase-approachability trade-off with abstraction & locality of context).
For arguments' sake though here is a quick-and-horribly-dirty example of JSX syntax separation (not recommended but demonstrative): https://codepen.io/lucideer/pen/jOZvwVz?editors=0010
In contrast with HTML, where there is no way one can mix the logic and the UI because it is syntactically impossible. You have to get the DOM element from a script and to fill it data (well, actually, you can with the script tag and on* attributes, but let's consider HTML without them, only allowing script tags in <head> for instance so our restricted version of HTML remains useful).
I think you need the rendering to be data, not code, to "forbid" this mix (and soon enough, you reinvent some kind of lisp I guess)
That's fair. If that's what you're looking for, then JSX is not the answer. I don't think we disagree though - I was merely pointing out separation is possible (even if not strictly enforced).
Personally, I am a fan of the component-driven model (criticised above for "blurring the lines"). As I mentioned, it's a trade-off, and I think any potential "blurriness" is far outweighed by the context and reduced abstraction wins from a code-readability & codebase approachability perspective. Heavily separated templating efforts often leads to codebases with deeply nested hierarchies for views -vs- controller logic that require having 4+ split pane editors open just to understand extremely local snippets of data flow. This is particularly egregious when e.g. trying to audit codebases for injection mitigation.
Think it may have being easier if JSX is just included in ES as a standard. So yes and no, JSX introduced by FB via react is a just a syntax sugar, however the original JSX is a meant to be a ES standard, with each node as a tree structure.
https://www.ecma-international.org/publications-and-standard...
E4X was supported by Firefox for a while, but I think support was removed.
For instance classes in JS are sugar syntax to define a function that defines fields in this and prototype members of this function.
Arrow functions are sugar syntax to define functions bound to a specific this.
async / await is sugar syntax for promises.
for..of is sugar syntax for iterating over an iterable.
The attribute renaming is a React feature. JSX doesn't rename attributes. See here for example https://codepen.io/lucideer/pen/jOZvwVz?editors=0010
> only expressions in brackets but full function calls in loops (map)
Not sure what you mean here. Function calls are expressions - they work bare in brackets & also as method args (like the arg passed to the map method on an array prototype, which is called while "loop"-ing that array). This is all Javascript functionality, not really specific to JSX in any way?
The problem with "only expressions in brackets" is that then you can write code in the template, but it's massively different to regular code. Worst of both worlds: code in templates and weird subset of code.
If this is undesirable as a feature, then yes, JSX is not an appropriate choice. JSX is the furthest thing from logic-less templating. But that's a deliberate design decision.
> it's massively different to regular code
It's not. It's just regular code - there are no differences.
> weird subset of code
It's not weird. It's any JS expression. All JSX brackets are values, and JS statements don't have return values, so embedding a JS statement within a JSX value would serve no purpose. What would it do?
All statements in JS can be expressed as expressions directly (ternary/array methods) or indirectly (nested within a function expression), so there's no loss of functionality - it's not even really a subset in that sense.
> All statements in JS can be expressed as expressions directly (ternary/array methods) or indirectly (nested within a function expression), so there's no loss of functionality - it's not even really a subset in that sense.
Do you not see the contradiction?
Vanilla javascript assignments can be any expression.
JSX assignments (the brackets) can be any expression.
There's no weirdness nor extra limitations to JSX assignments compared to normal vanilla JS. It works exactly the same.
If you think not being able to assign JS blocks is weird you're going to have to explain to me what this piece of JS code would do:
const val = if (x < y) { func(); } <div>{if (list?.length > 0) {
list.map(e => {
if (e.items.length) {
<div>Excellent!</div>
} else {
<div>Not good.</div>
}
});
} else {
<div>Nothin to see.</div>
}}</div>
Now, if you want to write this in actual JSX, you have to do this: <div>{(!!list && list.length) // awkward way of writing code
? list.map(e => {
if (e.items?.length) { // normal way of writing code
return <div>Excellent!</div>;
} else {
return <div>Not good.</div>;
}
})
: <div>Nothin to see.</div>
}</div>
Do you see the contradiction of being forced to use only expressions, only in some places? And this happens all the time. The most frequent thing we do in UI is rendering lists, so we use `.map` with "regular" code constantly, mixed with the awkward "expressions only" areas. Sure, the reason is that JavaScript is like that, but that doesn't make JSX any better.I find JSX extremely hard to read and work with and reason about.
Small example for people to understand the difference:
// HTML & JSX
<div id="person">
<h1>Niko</h1>
</div>
// Hiccup
[:div#person
[:h1 "Niko"]]In JSX you might be struggling with expressing certain things, because JS has a statement expression syntax. So you have to circumvent that. In Clojure everything is an expression already.
In JSX you can manipulate components with HoCs. In Clojure it’s just data, no special ceremony needed.
On the client, if you’re using React, you might use hooks to keep travk of state, which are a special construct that don’t exist in JS. In Clojure, if you use something like reagent, you just use atoms, they have a special purpose implementation, but they look and feel like regular old atoms.
However I have to say, JSX and React are very productive even with those limitations, simply because the tooling around it is so good.
XHP was launched in 2010 (https://www.facebook.com/notes/10158791323777200/)
The first version of FaxJs (the precursor to React) was launched in 2011, being directly inspired from XHP (https://github.com/jordwalke/FaxJs)
React was made in 2012 by the same person who made FaxJs, taking the best ideas from FaxJs and creating React.
So yeah, JSX actually comes from the idea of XHP :)
The concept was popular at Facebook, so it made its way into HPHP, HHVM, and later ReactJS.
Somehow JSX seems to be "worst of both worlds" to me.
Some of these HTML-templates-as-code libs (like Kotlinx.html) are generated from a formal HTML specification. This is really nice, and makes it more type safe (only allow tag nesting that is allowed, and only allow attributes that are allowed; ofcourse with escape hatches).
\<h1>Hello, world!\</h1>
\<img alt="Hello, world!"/>
\<h1>Hello, {place}!\</h1>
\<img alt={message}/>
But this doesn't: \<img alt="Hello, {place}!"/>
And as other commenters note, it's designed around React internals, meaning you get rules around capitalisation that wouldn't otherwise exist. And so on. <img alt={"Hello, " + place}/>
Or, for more complex interpolation: <img alt={`Hello, ${place}`}/>Visual Basic .NET has XML literal support [1].
[1]: https://docs.microsoft.com/en-us/dotnet/visual-basic/program...
https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Rel...
Had E4X been more widely released, I might have used it, as might many others. In retrospect, though, it's probably good that it didn't catch on, as it introduced a lot of extra syntax and operators, like a.@b, a.@*, a.*, a.b::c, a..b, a.(@b==x) and had semantics that affected large parts of the JS Runtime (how the delete operator works, how calling works, what += means, and so on).