Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I've also been using JSX since the good old days, when a component was just a function -- "hyperscript" (such as it is) was built right in. Notably, writing React apps in CoffeeScript was beautiful:

    div
      className: "greeting"
      "Hello, world!"
As you pointed out, the biggest problem with JSX is not that it isn't JS, it's that it isn't HTML. It's a leaky abstraction. Camel casing is only the most obvious problem, things like className and htmlFor are more insidious.

So as soon as a developer realizes that it's just sugar over JS, they are in a world of trouble, invariably trying to stick an if-else into it. If everyone had enough grounding in language theory to tell them: "JSX is just a JS primary" all would be well, but alas, that's putting the cart before the horse.



JSX always felt hacky - the cleanest thing I've seen in this area is ClojureScript and Reagent. And that goes for the whole React stack - it just feels like it was made in a wrong language - even the surrounding stuff like Redux.

Every single concept they hacked on to JS (immutable types, atom, declarative DSL, etc.) is a first class concept in CLJS - and it works beautifully even when building on top of their JS implementation - I feel sad they didn't just go "all in" on something like CLJS - they have more than enough resources to fix any implementation issues (ie. they have the resources to create a compiler that would generate code you would hand write with immutable.js and JSX - after all they are funding stuff like Flux and babel).

I understand why they didn't do it but it still feels so bad to see a hack in a place where a beautiful solution was just a step away.


Or even more beautiful - purescript-thermite. But just as js people are scared of Clojure, Clojure people are scared of Haskell :)

(it's a joke)


I've been a Clojure dev full time for a few years, and last year I looked into Haskell quite a bit [1]. But ultimately the fact that Clojure can do live-programming is what really kept me preferring Clojure. And I'm not even talking about that figwheel stuff. I mean just being able to mess around inside the JVM live from an Emacs buffer via Cider, and reloading parts of my code while my app is still running during development. I'm not interested in giving that up, it's made me more productive than I thought I could ever be.

[1]: http://sdegutis.github.io/


Live coding with ClojureScript/Reagent/Re-frame/Figwheel/REPL is a holy-grail-kind of dev experience for me (and React really does feel like it was ported to JS from a better place), but one has to admit the potential maintainability/refactorability issues when projects grow beyond a certain size (as compared to something like Haskell or PureScript).

Plumatic Schema [1] goes a long way towards narrowing that gap though and I cannot recommend it enough. Whether it goes far enough in terms of safety is certainly a matter of project type/size and personal preference, but to me, for my kind of work so far it does and they'll take away my ClojureScript when they pry it from my cold, dead hands. :)

Also (and slightly off-topic) the combination of clairvoyant + re-frame-tracer [2][3] (+[4] for some minor, so far mostly React Native-relevant additions) should be way more popular than it seems to be. It's definitely one of the most important tools in my toolbox and completely changed the way I approach debugging.

[1]: https://github.com/plumatic/schema [2]: https://clojars.org/day8/re-frame-tracer [3]: https://clojars.org/gnl/re-frame-tracer [4]: https://clojars.org/gnl/clairvoyant


You can do that in Haskell as well though [0]. With ghci, making a code change is almost instantaneous even for big code bases, and you are assured that your code is self consistent. Then mess with your long-running state all you want.

At least for backend stuff, this is no worse than Clojure.

Give it a try :) Ping me if you have any questions.

[0] http://chrisdone.com/posts/ghci-reload


This is one part of the CLJS story that I think prevented it from becoming more widespread - it lacked a good REPL/compile story for a long time because of closure compiler. I would almost characterize that decision as a premature optimization - they focused on producing small output from the start, IMO larger JS size wouldn't matter that much in majority of use cases (you won't use CLJS to write websites, and webapps can tolerate few hundred k or even a MB of JS that's easy to cache), but they gave up one of the signature strong points for CLJ/Lisp so it wasn't as attractive even to CLJ devs.


I'd like to learn enough to understand the statement "JSX is just a JS primary," and I can't find out what a "$lang primary" is in PLT. Can you point out some resources for me to figure this out?


The full name is primary expression. The meat of it is that a primary is usually just a literal value, identifier, or something in parentheses, but it varies based on the particular language.

For a deep dive you'll want to read resources about parsing. To name one article that came up recently on HN, take a look at "Why Parsing Tools are Hard" [0].

[0]: http://blog.reverberate.org/2013/09/ll-and-lr-in-context-why...


The previous comment is trying to sound smart by using obscure terminology. I would guess they mean to say that JSX is a translated subset of JS?


Thanks for your generosity. This is what I was referring to: JSX extends the PrimaryExpression in the ECMAScript 6th Edition (ECMA-262) grammar.

Please take a look at the draft JSX spec [0] for details.

[0]: https://github.com/facebook/jsx


Replacing JSX with Coffeescript is really beautiful, and makes large components much more readable. I am a bit worried as it does not have much traction. JSX does not even allow to copy-paste from HTML as we need to rename all keys containing hyphens with some CamelCase.

Here is some of my Coffeescript render function, it is much more elegant than the equivalent JSX.

render: -> div className: "btn-group" role: "group" style: width: '100%'

        for option in @props.options
            label
                key: option.value
                className: @buttonClass @state.selected == option.value, option.bsColor
                style:
                    minWidth: (100 / @props.options.length) + '%'
                input
                    type: 'radio'
                    required: true
                    name: @props.name
                    value: option.value
                    checked: @state.selected == option.value
                    readOnly: false
                    onClick: @handleClick
                    "data-key": option.value
                    option.label


It doesn't have as much traction because as a whole, coffee script is almost always unreadably ambiguous (even moreso than jsx).

And the best parts are already here in es2015.


In what sense are you using the word "primary" in "JSX is just a JS primary"? I have a passing interest in language theory and strong interest in PL theory, but I don't think I've seen usage that before.


I specialised in programming languages in university, and I, too, have not heard of that term. :/ @OP: some exposition please?


The full name is primary expression, things like literal values, identifiers, and other expressions in parentheses.


Thanks!




Consider applying for YC's Fall 2026 batch! Applications are open till July 27.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: