Ternary operators should never be nested, whether you're using JSX or not. If you have that many conditionals you should use variables and/or decompose the optional pieces into sub-components. Pretty much any time you have a tag that has a huge number of attributes, it's a smell that you need to decompose something.
Variable assignment is the simplest answer, which takes advantage of the fact that null or undefined values are ignored in JSX:
const Dashboard = (props) => {
let avatar;
if (props.user) avatar = <Avatar user={props.user} />;
return (
<div>
{avatar}
...some other content...
</div>
);
};
Regarding class vs. className: class is a reserved word in JS. It's not really a perf thing, it's the fact that JSX was intended as a very simple transform. If JSX used class instead of className, the transpiler would need to be contextual since "class" would sometimes mean "css class" and sometimes "JavaScript class". The baseline complexity for the parser would be higher and could lead to all sorts of complexity. Rather than deal with that the React team avoided the problem by using className instead, keeping things simple.
I think this proves lhorie's point. Markup syntax is dominated by code when you are building complex dynamic apps instead of static documents. What do you really gain by putting angle brackets around Avatar instead of calling a function?
FWIW I believe new react devs are slow to realise they can use local variables like this because JSX looks like it is doing string templating instead of object instantiation.
The example I gave was simplistic, but the value of JSX is the ability to easily nest elements. For instance, let's take my previous example and say we're creating a profile link:
const Dashboard = (props) => {
const {user} = props;
let link;
if (user) {
link = (
<a href="...">
<Avatar user={user} />
<span>{user.name}</span>
</a>
);
}
return (
<div>
{link}
...some other content...
</div>
);
};
If you want, you could create a `createProfileLink()` function, or you could create a `ProfileLink` component, or you could keep it as a variable in the `render()` function. This flexibility is what makes JSX powerful.
> but the value of JSX is the ability to easily nest elements
There is nothing there that "makes JSX so powerful", its just hiding function calls and varargs. Its only xml-ish syntax. You are welcome to prefer it but its not adding anything functional beyond that.
const Dashboard = (props) => {
const {user} = props;
let link;
if (user) {
link =
DOM.a({href: "..."},
Components.Avatar(user),
DOM.span(user.name));
}
return
DOM.div(link, ...some other content);
};
Yes, I understand how JSX works. My point is that it permits nesting in a syntax that is much simpler and emulates markup, which is familiar to web developers.
It's okay if you prefer to write code using the direct function calls, but I'm not sure most people would agree with you. I've built a product using direct calls (in CoffeeScript) and using JSX, and JSX was far easier to work with and less error-prone. YMMV.
I disagree in two ways: the first is that the ability to write template composition procedurally isn't specific to JSX. You can do that in plain js/hyperscript just as well.
The second point is precisely that this is procedural code. If the ability of putting together templates procedurally is the pinnacle of templating power/expressiveness, we might as well go back to Backbone.js.
> Regarding class vs. className: class is a reserved word
> in JS. It's not really a perf thing, it's the fact that
> JSX was intended as a very simple transform. If JSX used
> class instead of className, the transpiler would need to
> be contextual since "class" would sometimes mean "css
> class" and sometimes "JavaScript class".
I don't think React should have used `class` instead of `className`, but this isn't the reason.
<foo className="bar" />
compiles to
React.createElement("foo", { className: "bar" });
It could have just as easily have been that
<foo class="bar" />
compiles to
React.createElement("foo", { 'class': "bar" });
as far as JSX is concerned (or even without the quotes in an ES5 world).
The output isn't the problem; it's that "class" is also a keyword in the JSX input. I admit, though, I'm not intimately familiar with the JSX transpiler and am just guessing as to their motives.
I'm actually fine w/ JSX being "dumb" and just translating `class` to `class`, but when used in conjunction w/ React, the end result is that the JSX "markup" has a lot of traps that simply don't exist in similar libraries like Mithril.
`className` isn't the only offender. `onClick` and `readOnly` are other notorious one. And then there's stuff like `xlinkHref`, because it's not like anyone ever imports SVG from external tools.
Variable assignment is the simplest answer, which takes advantage of the fact that null or undefined values are ignored in JSX:
Regarding class vs. className: class is a reserved word in JS. It's not really a perf thing, it's the fact that JSX was intended as a very simple transform. If JSX used class instead of className, the transpiler would need to be contextual since "class" would sometimes mean "css class" and sometimes "JavaScript class". The baseline complexity for the parser would be higher and could lead to all sorts of complexity. Rather than deal with that the React team avoided the problem by using className instead, keeping things simple.