JSX feels "honest" - like an authentic extension of JavaScript. Yes there are a few quirky rules but I hated the custom angular attributes etc...
I've only had to do a little Angular development in my life but something I remember was how hard it was to get answers on basic stuff. Like I would have a problem that I'm sure was trivial and people run into all the time and I couldn't Google and get a result that wasn't full of really dense Angular concepts and keywords.
It's a hard framework to just kind of nose your way into if you need to update something. It's like it wants you to read all the documentation and learn all the fancy words it has for stuff.
[1] https://github.com/jorgebucaran/hyperapp/tree/main/packages/...
It's semi-directly related to (subset of a) JavaScript standard which it evolves some of the more useful syntax for some modern needs. It's just not an "active" standard currently targeted by browsers today (in part because it need evolution): ECMA-357 aka E4X aka ECMAScript for XML. [1]
There's currently no interest in adding browser support for JSX (either from the JSX spec itself or any browser makers), just as E4X support waned very quickly when Firefox was the only browser interested in supporting it, but that doesn't mean it is impossible to see browser support at all in the future. It was standardized once, it might be standardized again now that we have a better idea of what it might be used for in the wild. (I don't think it will be, mostly because there's an ecosystem of interesting non-React usages of JSX that would be hampered a bit if it wasn't just a transpiler step.)
That's pretty convenient.
JSX is valid JS. It is converted down to the same thing as what you describe, function calls to React.createElement(). Which can also be used instead and aliased to a function if you prefer.
Using "HTML" like syntax in JSX then let's React not have to invent it's own base components and let's you think about the "HTML" as HMTL.
You could even alias all the elements to function names
const h1 = (...) => {
React.createElement({...})
}
and then call those functions like so h1(...)
across your components instead of <h1> ... </h1>. const MyComponent = () => {
return (
div(
h1(...)
h2(...)
p(...)
items.map(item => li(item))
)
)
}
A "component" is just a JS Object that you can manipulate and pass through wherever you want like anything else.This is disingenuous. Browsers do not understand JSX, nor do most JavaScript engines. TypeScript also gets transpiled to JavaScript -- it is not valid JavaScript in and of itself, you require a build step. We can argue semantics, but I think it's pretty clear what I meant.
> You could even alias all the elements to function names
You've just recreated what I mentioned two comments above in this same comments thread. :) See: https://github.com/jorgebucaran/hyperapp/tree/main/packages/...
This is what I'm arguing for over something like JSX.
I'm only illustrating that the difference between JSX and JS for React is about syntax and not the core distinction of why React feels easier to work with compared to angular/vue/svelte etc which all invent their own mini languages. JSX feels much more natural since it allows for the same JS everyone (hopefully) loves.
Something like hyperapp/hyperscript can absolutely be used in place of JSX, but the HTML likeness that JSX enables feels more natural to me - and I think most - vs a bunch of h1(), h2() etc function calls. In the end, though, this is a trivial difference.
A component expressed in JSX is really just a JS function call that ends up as a document.createElement() invocation.
‘const [count, setCount] = useState()’
is normal javascript? It runs completely counter to the way functions and variables normally work, using some global store behind your back.
The idea that react is “just javascript” has gone out the window with hooks.
const [x, y] = [0, 0] // point destructuring
If you really wanted to, you could always feel more at home by doing it the old pre-ES2015 way:
var countState = useState()
var count = countState[0]
var setCount = countState[1]
That's the same code. It's not even that different from how JS functions have always worked.
const [x, y] = getPoint()
No one would accuse a function named "getPoint()" of using a global store "behind their back", they assume it is "getting" the "point" from somewhere, certainly, but wouldn't necessarily know where (or care where in most cases if you are just using someone else's library or component). It could be using a window.point global, it could be making an XHR/fetch request to an API somewhere, it could be creating random points, it could be trying `this.point` and depending on any nearby Object.bind() or Object.apply() that `this` could be nearly any object (including window, but not necessarily). (JS's objects have always been that weird. That's JS's normal.) There are so many options and that's the nature of function calls you have no idea without seeing its implementation.
The useState implementation is particularly a black box in React, but it's no more a "black box" than the the average "normal" function.
Also all the spooky "Rules" about using hooks (maintaining their order, making sure they are never used in branches, etc) exist because it is not just using a global store! It is essentially using a curiously bound `this`, which again is very normal JS OOP going way back to the beginning of the language. It doesn't look like a normal object and React's developers don't want to call hooks "objects" to avoid confusion and because they are easier to program if you don't call them "normal weird JS objects" and use some fancier functional programming abstractions, but they very much are "normal weird JS objects". You don't see the weird Object.bind (equivalents) because the framework is taking care of those for you, but it's not the first (and it will not be the last) JS framework to give developers a black box API that looks confusing from the outside and asks you to trust it is doing the right thing inside.
Considering idiomatic React basically necessitates JSX, no, React does not do it the best. Frameworks that embrace things like hyperscript and regular .js files over unnecessary aesthetics and goofy file extensions like .jsx do this better than React (Preact, Mithril, Hyperapp). Even hooks are weird and magical to JS veterans -- most people hopping into React are essentially told "just accept this, it works, and you don't have to understand how".
Maybe it's the understanding that they integrate with React's event system (which I think is powered by something like rxjs/observables), but hooks make the most sense once you start implementing custom hooks which are incredibly easy to write and reuse.
Need a hook for undoable (and re-doable) state? It can be implemented in ~30 lines and then used anywhere in your application.
Need a hook to manage data from an API across your application, a custom hook makes this trivial especially if you need to connect it with your global state management (like redux/context/etc).
JSX is nothing special and it's possible (and trivial) to set up your component files to use a .js extension.
The only thing JSX does is let you write components with an HTML like syntax instead of with a bunch of function calls. I find this extremely ergonomic.
Bad React is when the two ideas - view and component logic - are mixed too much. That's the point at which components need to be broken down further to avoid bloat or a custom hook is needed to handle data.
You end up having to extend the framework in potentially weird ways to get your thing to work.
It's much nicer when your framework just uses the underlying system instead.
Thinks such as the performance, the reactivity model, the "gotchas", the ecosystem, the libraries, the tooling, etc are far, far, far more important than "I like IFs done this way".
This is the same thing as when people discard Tailwind because "I don't like reading that many classes". There's so much more behind it to like or dislike it.
The React primitives, especially today, are so easy to work with. Components in JSX can be treated like an object. They are functions that have a return value. They use hooks which are also just functions that return values. Both can be combined, composed, and manipulated with one another using the JS everyone knows (and I at least love).
Frameworks should be built up to preserve the structure that the language provide.
React does this the best.
It's not a framework like Angular but it's not meant to be. That's why we've also created frameworks like NextJS, and soon Remix (remix.run), and other solutions.
Even when using {} in react, the thing in the curly braces is JS. I'm not using a framework's invented conditional implementation, I'm using JS's conditional expression. I have access to the language and don't need to learn the framework's equivalent which is usually more verbose and less direct.