3 ms·
Some of this isn’t right or deserves clarification. > It must only return a single element Assuming you mean “return” as in a JSX expression in a return state
by eyelidlessness 3y ago
Some of this isn’t right or deserves clarification.
> It must only return a single element
Assuming you mean “return” as in a JSX expression in a return statement (though the same applies to a JSX expression in any valid syntax position), it can be any of:
- one Element (which may or may not correspond to any markup element, it can resolve to basically anything depending on implementation)
- zero Elements (<></>)
- a non-Element child-compatible expression (typically a primitive value in most implementations)
- any arbitrary non-Element expression (behavior will vary depending on implementation support)
- N Elements (<>…</>)
> you can’t add arbitrary attributes
This is entirely implementation dependent. Attributes aren’t even part of the syntax (they’re “props”), and many implementations differ on how or even if they correspond to attributes at all. The spec does not constrain arbitrary prop names.
> its control flow syntax seems (subjectively) bolted on
It’s actually the inverse: control flow is anything that can be used in a JS expression position; JSX is bolted on (extends) the expression syntax. Some implementations and/or libraries also implement control flow as JSX Element expressions (eg Solid’s For, Show, Switch/Match).
> When you’re coming from a language where you can print anything, it's very frustrating.
The only real limitation syntactically is that everything in a JSX expression must be an expression itself. This isn’t as limiting as it sounds, because functions can be expressions (with anything in their body, and can be invoked as an expression inline at their definition site).
It might help to think of JSX as more like an S-expression (as in Lisp). It can express any value (that the language can produce), but it can’t express arbitrary statements.
- tambourine_man 3y ago> Assuming you mean “return” as in a JSX expression in a return statement I do. Right, but the <></> syntax still feels like a hack around a need to have just one node at the top of the three. ----------- >Attributes aren’t even part of the syntax (they’re “props”) What I meant was that this is valid syntax: function hey ({ props }) { return ( <div data-foo={ bar }></div> ); } While this isn't: function hi ({ props }) { return ( <div { bar }></div> ); } There are many situations in HTML where you want a plain string inside the tag, like <input checked> ----------- > control flow is anything that can be used in a JS expression position I explained myself poorly. We can use if/else outside the return statement, of course. It's JS after all. But inside it, which is where the JSX magic happens, you have to resort to things like: { isItTrue ? ( <i>yep</i> ) : ( <b>nope</b> )} ----------- >It might help to think of JSX as more like an S-expression (as in Lisp) That's probably the biggest complement to JSX possible :) I admire Lisp from afar, but could never stand the parentheses.
- eyelidlessness 3y ago> Right, but the <></> syntax still feels like a hack around a need to have just one node at the top of the three. It’s roughly analogous to an array (and in some implementations it literally produces an array). The “hack” isn’t around returning multiple nodes, you can’t produce (and therefore return) an expression of multiple anything without some container. > There are many situations in HTML where you want a plain string inside the tag, like <input checked> Some implementations do accept that (checked prop without any curly braces or prop value assignment), with roughly the same semantics (the prop is assigned a boolean true). React doesn’t accept it IIRC, but React has quite a few rules beyond JSX (as specified, and as used in other implementations). > But inside it, which is where the JSX magic happens, you have to resort to things like: You don’t! You only have to use an expression. This is perfectly valid JSX (assuming whatever is outside the outer curly braces is also valid): {(() => { if (isItTrue) { return <i>yep</i>; } else { return <b>nope</b>; } })()} > That's probably the biggest complement to JSX possible :) I admire Lisp from afar, but could never stand the parentheses. It really is a pretty close analogy, not just a compliment. And in most uses, JSX is almost exactly akin to a Lisp macro (the biggest difference besides delimiters and host language semantics is that the “macro” definition is supplied by some arbitrary tooling external to the host language).
- tambourine_man 3y ago> You don’t! You’re right, but I’m not sure wrapping it in a self calling function is any better to me. It feels like a lot of contortionism to just echo strings.
- eyelidlessness 3y agoSure, that’s reasonable if your only concern is echoing strings. Part of what’s appealing to me about JSX is that it’s capable of far more than string output (even in that’s ultimately all you’re producing from it). The thing (usually) produced in a JSX expression is a value, which can be any arbitrary data structure, and can be composed in any arbitrary way you like. Echoing strings—which is to say producing output as a side effect, out of band of a component’s return value—undermines that. It’s totally a valid approach (and makes perfect sense in the context of PHP’s rendering model), it just has a different set of capabilities.