React & Coffeescript

Multiple people asked what's the story about JSX and CoffeeScript. There is no JSX pre-processor for CoffeeScript and I'm not aware of anyone working on it. (If you are interested in writing one, you probably should look at CoffeeScriptRedux). Fortunately, CoffeeScript is pretty expressive and we can play around the syntax to come up with something that is usable.

Example

Let's see how JSX look like with an example:

<div classname="MarkdownEditor">
 
 
<h3>Input</h3>
 
 
  <textarea onkeyup="{this.handleKeyUp}" ref="textarea">    {this.state.value}
  </textarea>
</div>

which desugars to the following

React.DOM.div({className: 'MarkdownEditor'}, [
  React.DOM.h3({}, 'Input'),
  React.DOM.textarea({onKeyUp: this.handleKeyUp, ref: 'textarea'},
    this.state.value
  )
])

We can easily translate it to CoffeeScript:

{div, h3, textarea} = React.DOM
(div {className: 'MarkdownEditor'}, [
  (h3 {}, 'Input'),
  (textarea {onKeyUp: @handleKeyUp, ref: 'textarea'},
    @state.value
  )
])

Structure

The translations rules are really easy. The only gotcha is to write the tags wrapped in parenthesis lisp-style. This is the best way I found not to get caught with indentation issues.

# Empty element
#
 
 
<div></div>
 
 
 
(div {})
 
# Text children: You use a string literal
#
 
 
<div>foo</div>
 
 
 
(div {}, 'foo')
 
# Interpolation: You ignore the {} and write the expression as is
#
 
 
<div>{this.state.text}</div>
 
 
 
(div {}, @state.text)
 
# Multiple children: You use the [] notation
#
 
 
<div>
  <b r="">
  <b r="">
</b></b></div>
<b r=""><b r="">
 
 
(div {}, [
  (br {}),
  (br {})
])
 
# Attributes: You write them using {} notation
#
 
 
<div onclick="{this.onClick}"></div>
 
 
 
(div {onClick: @onClick})
</b></b>

Demos

I've re-written all the React front-page examples using CoffeeScript. The translation was really easy.

Hello World

Timer

Todo

Markdown

If you liked this article, you might be interested in my Twitter feed as well.
 
 

Related Posts

  • November 4, 2013 Bitwise Truthiness (0)
    In this blog post, I explore another form of truthiness in Javascript. What happens if you use a bitwise operator on a value like 0|value or ~~value. Context We recently turned on the JSHint bitwise rule by default and the following code was caught. var isValid = false; for […]
  • December 7, 2011 Automatic Links with Trie (0)
    On MMO-Champion, we often paste World of Warcraft patch notes taken from Blizzard. The main problem is that it's plain text. We want to be able to add links to all the spells, quests, zones ... This way people can mouseover and see the description. It helps figuring out what […]
  • January 25, 2017 Anatomy of a JavaScript Pretty Printer (2)
    During the past few weeks, I've been working on prettier, which is a JavaScript pretty printer. We are approaching the phase where we can actually use it so this is a good time to explain how it works. We're going to go through an example if (!pretty) { makePretty() } String […]
  • September 12, 2015 React Europe Keynote (0)
    I can't believe that I had the opportunity to do the opening session of React Europe, in front of 700 people! This is total madness how big this React thing has become and I'm so lucky to be able to play a small part of it. In this talk, I tried to give an overview of the front-end […]
  • September 22, 2011 URLON: URL Object Notation (43)
    #json, #urlon, #rison { width: 100%; font-size: 12px; padding: 5px; height: 18px; color: #560061; } I am in the process of rewriting MMO-Champion Tables and I want a generic way to manage the hash part of the URL (#table__search_results_item=4%3A-slot). I no longer […]