4 ms·
> JSX is a gotcha-riddled kludge to clumsily shoehorn HTML into a JavaScript function return. The only thing worse than using JSX with React is not using JSX wi
by strken 4y ago
> JSX is a gotcha-riddled kludge to clumsily shoehorn HTML into a JavaScript function return. The only thing worse than using JSX with React is not using JSX with React.
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):
const TodosList = ({ todos }) => (
<div class="todo-list">
{
if (todos.length > 0) {
todos.map(t => <Todo key={t.id} todo={t} />);
} else {
<p>No todos yet</p>
}
}
</div>
);
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.
- somewhereoutth 4y ago> HTML's a tree. Function calls are a tree. They're similar in nature and they map cleanly to each other 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.
- alex504 4y agoAs soon as I see the JSX critique I roll my eyes. This has been around since reacts inception and it just doesn't hold any water for me. I remember interviewing with a company in 2019 that was still on Angular 1 because they didn't like JSX, and didn't want to learn typescript. It just "looked yucky" to them. 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.
- cheald 4y agoI understand the instinctive reaction against JSX. I did a lot of Perl and PHP way back when, when it was super common to have bits of template sprinkled hither and thither with logic woven in here and there, and it made maintainability a nightmare. When the world moved on to dumb templates and embrace of MVC, it was a huge relief. JSX felt like a regression in that regard, but in practice, I think it ends up being pretty straightforward, in part due to the lack of any real flow control inside of it, and in part because of the convention of having small functional components which return a JSX tree, rather than bits of JSX just popping up everywhere here and there.
- mmis1000 4y ago> JSX felt like a regression in that regard, but in practice, I think it ends up being pretty straightforward > 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)
- cheald 4y agoYou can definitely do JSX wrong. React doesn't do a whole lot to protect you from it, it's true. But, in a project which uses it well, I hate it a lot less than I once did.
- tuukkah 4y ago> in ES-like pseudocode 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> );
- strken 4y agoProbably should have been more clear. It's not that the ternary operator is horrible when used judiciously in a small toy example, it's that it's difficult to parse with longer blocks of code or any complicated flow control. Consider the following very contrived example: 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> );
- tuukkah 4y agoThanks for expanding! And do you see my other three refactorings similarly lacking? 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.