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 (2)
    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 […]
  • August 19, 2011 Javascript – Stupid Idea: Hoisting at the end (133)
    JSLint imposes us to do manual hoisting of variables. What if we did it but at the end of the function? :P How you write function print_array (array) { var length = array.length; for (var i = 0; i < length; ++i) { var elem = array[i]; console.log(elem); […]
  • 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 […]
  • January 25, 2017 Anatomy of a JavaScript Pretty Printer (10)
    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 […]
  • December 7, 2011 Automatic Links with Trie (1)
    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 […]