Very very poor reasoning. I have never thought to myself, man I wish this wasn't JSX and just normal Javascript, to myself in the 6 or so years I've been using React. It just isn't something that anyone should care about and it shows the author has probably been biased against React forever, for no good reason.
> rather than bits of JSX just popping up everywhere here and there.
I did see lots of codebase write jsx like this. So I hate it. I starts the journey of front-end from jquery, ejs, angular.js, react to vue. And jsx of react always feels like a bad step to me.
Yes, If you write jsx properly, then it is just as readable as a normal template. But somehow some people never get it. And react also never made any attempt to stop insane codebase like this to exist.
(And you'd better pray your previous codebase owner isn't one of these, or you are in a big trouble)
In valid ES, you have many options even if none is perfect.
With the "horrible" ternary operator:
const TodosList = ({ todos }) => (
<div class="todo-list">
{
(todos.length > 0)
? todos.map(t => <Todo key={t.id} todo={t} />)
: <p>No todos yet</p>
}
</div>
);
Without the ternary operator: const TodosList = ({ todos }) => {
let todoContent;
if (todos.length > 0) {
todoContent = todos.map(t => <Todo key={t.id} todo={t} />);
} else {
todoContent = <p>No todos yet</p>;
}
return (
<div class="todo-list">
{ todoContent }
</div>
);
};
If you allow the repeat of the div: const TodosList = ({ todos }) => {
if (todos.length > 0) {
return (
<div class="todo-list">
{ todos.map(t => <Todo key={t.id} todo={t} />) }
</div>
);
} else {
return (
<div class="todo-list">
<p>No todos yet</p>
</div>
);
}
};
With a separate render function: const renderTodos = (todos) => {
if (todos.length > 0) {
return todos.map(t => <Todo key={t.id} todo={t} />);
} else {
return <p>No todos yet</p>;
}
};
const TodosList = ({ todos }) => (
<div class="todo-list">
{ renderTodos(todos) }
</div>
); const Todo = (todo) => (
<div class="todo">
{todo.status === 'UNFOOABLE'
? <UnfooableError todo={todo} />
: todo.size === 'GIGANTIC'
? <TextBox value={todo.body}>
: (
<div>
<p>I've run out of creativity but just imagine this has more stuff</p>
<p>And that there's a good reason not to make this its own component</p>
<OneLineTextBox value={todo.body} />
</div>
)
}
</div>
);To me it sounds as if you just didn't like JavaScript: the statement vs expression distinction constrains all non-JSX code too, e.g. you need to use the ternary operator to conditionally assign a value to a const variable.
Similarly, your example functions have long multi-line expressions as bodies so for the small gain of not needing the curly braces and a return statement, you pay a huge cost of not being able to use any statements in your code.
No, all four are fine and most people use them in code all the time. They're not completely identical to ternary operators because they move the location of the JSX outside the place where it's used, which can make it harder to read the code at a glance.
> it sounds as if you just didn't like JavaScript
Yeah, I see that as a failure of EcmaScript, as I said in the first comment. JSX has to work within the unfortunate boundaries of the language.
> for the small gain of not needing the curly braces and a return statement, you pay a huge cost of not being able to use any statements in your code
That wasn't intended to be a meaningful part of the example, I was just writing the shortest component that let me show a particularly style which would be nice to have in EcmaScript instead of ternary operators.
Yes, this is a key point. Indeed, many other 'constructed artifacts' compose nicely as trees, and thus functional languages are a natural fit for defining them parametrically.
Not sure I understand this, or if I do understand it, I definitely don't agree. HTML's a tree. Function calls are a tree. They're similar in nature and they map cleanly to each other.
> Or how you can’t use some standard HTML attributes in JSX (because JSX doesn’t know the difference between a React prop and an HTML attribute). Or memoization. Or how there aren’t real conditionals, so you have to rely on short-circuit operators. Or how preventing infinite loops is your responsibility—even though there aren’t really loops, so you have to use array methods…you know what, let’s just move on.
These are natural consequences of representing HTML as code, and they help me understand the first quote a bit better. I still don't think JSX is bad. Putting flow control into the template language in the style of Vue, Angular, or even the supposedly logicless Mustache ends in a programming style that I dislike, where the dividing line between template logic and logic in the actual code isn't clear, and you need to refactor heavily when you reach the gaps in what the template language lets you do.
They're closer to failures of EcmaScript. Coffeescript and Ruby weren't ideal, but their syntactic sugar would have let you do (in ES-like pseudocode):
Blending code and data can look a bit scary, but it lets you copy the blocks of code around like normal. You could (in a theoretical world where if statements returned the result of the last line of the branch) just copy that code outside the JSX, and have it work properly. With horrible JSX ternary operators you still have to rewrite, but that's the fault of the JS part of JSX not the underlying language-agnostic concept, and it's still something I prefer to putting logic in the template language itself.