You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

310 lines
35 KiB
Plaintext

9 years ago
<!DOCTYPE html>
<!-- saved from url=(0071)http://sc5.io/posts/using-reacts-jsx-with-coffeescript-and-sublime-text -->
<html class=" js touch history csstransforms3d csstransitions svg positionfixed no-android no-ios no-wp no-ie overflowscroll no-ipad no-ipad3plus"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<title>SC5 - Using React's JSX with CoffeeScript and Sublime Text</title>
<meta name="description" content="sc5.io">
<meta name="author" content="sc5">
<!-- http://t.co/dKP3o1e -->
<meta name="HandheldFriendly" content="True">
<meta name="MobileOptimized" content="320">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="google-site-verification" content="y6R1l0y-v-gTPLR98ndaX3x99ktqhsHrnzlr89DRXXk">
<meta property="fb:app_id" content="391511784314846">
<meta property="og:title" content="Using React&#39;s JSX with CoffeeScript and Sublime Text">
<meta property="og:type" content="website">
<meta property="og:url" content="http://sc5.io/posts/using-reacts-jsx-with-coffeescript-and-sublime-text">
<meta property="og:image" content="http://sc5.io/blog/wp-content/uploads/2014/06/react.png">
<meta property="og:description" content="">
<meta property="og:site_name" content="SC5">
<meta name="theme-color" content="#ef4942">
<!-- For non-Retina iPhone, iPod Touch, and Android 2.1+ devices: -->
<link rel="apple-touch-icon-precomposed" href="http://sc5.io/static/apple-touch-icon-72x72-precomposed.png">
<!-- For first- and second-generation iPad: -->
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="http://sc5.io/static/apple-touch-icon-72x72-precomposed.png">
<!-- For iPhone with high-resolution Retina display: -->
<link rel="apple-touch-icon-precomposed" sizes="114x114" href="http://sc5.io/static/apple-touch-icon-114x114-precomposed.png">
<!-- For third-generation iPad with high-resolution Retina display: -->
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="http://sc5.io/static/apple-touch-icon-144x144-precomposed.png">
<link rel="shortcut icon" href="http://sc5.io/static/favicon.ico">
<link href="./react_files/css" rel="stylesheet" type="text/css">
<link rel="alternate" type="application/rss+xml" title="SC5 Blog RSS Feed" href="http://sc5.io/blog/feed/">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui">
<style>
@font-face {
font-family: 'gthm_medium';
src: url('/fonts/gotham_rounded_medium-webfont.eot');
src: url('/fonts/gotham_rounded_medium-webfont.eot?#iefix') format('embedded-opentype'),
url('/fonts/gotham_rounded_medium-webfont.woff2') format('woff2'),
url('/fonts/gotham_rounded_medium-webfont.woff') format('woff'),
url('/fonts/gotham_rounded_medium-webfont.ttf') format('truetype'),
url('/fonts/gotham_rounded_medium-webfont.svg#gotham_rnd_ssmmedium') format('svg');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'gthm_book';
src: url('/fonts/gotham_rounded_book-webfont.eot');
src: url('/fonts/gotham_rounded_book-webfont.eot?#iefix') format('embedded-opentype'),
url('/fonts/gotham_rounded_book-webfont.woff2') format('woff2'),
url('/fonts/gotham_rounded_book-webfont.woff') format('woff'),
url('/fonts/gotham_rounded_book-webfont.ttf') format('truetype'),
url('/fonts/gotham_rounded_book-webfont.svg#gotham_rnd_ssmbook') format('svg');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'nws_icon';
src: url('/fonts/nws_icon.eot?-ngavj3');
src: url('/fonts/nws_icon.eot?#iefix-ngavj3') format('embedded-opentype'),
url('/fonts/nws_icon.woff?-ngavj3') format('woff'),
url('/fonts/nws_icon.ttf?-ngavj3') format('truetype'),
url('/fonts/nws_icon.svg?-ngavj3#nws_icon') format('svg');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'linkedin_icon';
src: url('/fonts/linkedin_icon.eot?-ngavj3');
src: url('/fonts/linkedin_icon.eot?#iefix-ngavj3') format('embedded-opentype'),
url('/fonts/linkedin_icon.woff?-ngavj3') format('woff'),
url('/fonts/linkedin_icon.ttf?-ngavj3') format('truetype'),
url('/fonts/linkedin_icon.svg?-ngavj3#linkedin_icon') format('svg');
font-weight: normal;
font-style: normal;
}
</style>
<link rel="stylesheet" href="http://sc5.io/css/styles-0.1.1.css">
<!-- Start Visual Website Optimizer Asynchronous Code -->
<script id="facebook-jssdk" src="./react_files/sdk.js"></script><script async="" src="http://www.google-analytics.com/analytics.js"></script><script id="hs-analytics" src="http://js.hs-analytics.net/analytics/1429382400000/469635.js"></script><script type="text/javascript">
var _vwo_code=(function(){
var account_id=83397,
settings_tolerance=2000,
library_tolerance=2500,
use_existing_jquery=false,
// DO NOT EDIT BELOW THIS LINE
f=false,d=document;return{use_existing_jquery:function(){return use_existing_jquery;},library_tolerance:function(){return library_tolerance;},finish:function(){if(!f){f=true;var a=d.getElementById('_vis_opt_path_hides');if(a)a.parentNode.removeChild(a);}},finished:function(){return f;},load:function(a){var b=d.createElement('script');b.src=a;b.type='text/javascript';b.innerText;b.onerror=function(){_vwo_code.finish();};d.getElementsByTagName('head')[0].appendChild(b);},init:function(){settings_timer=setTimeout('_vwo_code.finish()',settings_tolerance);this.load('//dev.visualwebsiteoptimizer.com/j.php?a='+account_id+'&u='+encodeURIComponent(d.URL)+'&r='+Math.random());var a=d.createElement('style'),b='body{opacity:0 !important;filter:alpha(opacity=0) !important;background:none !important;}',h=d.getElementsByTagName('head')[0];a.setAttribute('id','_vis_opt_path_hides');a.setAttribute('type','text/css');if(a.styleSheet)a.styleSheet.cssText=b;else a.appendChild(d.createTextNode(b));h.appendChild(a);return settings_timer;}};}());_vwo_settings_timer=_vwo_code.init();
</script><style type="text/css"></style><script src="http://dev.visualwebsiteoptimizer.com/j.php?a=83397&u=http%3A%2F%2Fsc5.io%2Fposts%2Fusing-reacts-jsx-with-coffeescript-and-sublime-text&r=0.552155762212351" type="text/javascript"></script>
<!-- End Visual Website Optimizer Asynchronous Code -->
<script type="text/javascript" charset="utf-8" async="" data-requirecontext="_" data-requiremodule="main-0.1.1" src="./react_files/main-0.1.1.js"></script><style type="text/css">.fb_hidden{position:absolute;top:-10000px;z-index:10001}.fb_invisible{display:none}.fb_reset{background:none;border:0;border-spacing:0;color:#000;cursor:auto;direction:ltr;font-family:"lucida grande", tahoma, verdana, arial, sans-serif;font-size:11px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:1;margin:0;overflow:visible;padding:0;text-align:left;text-decoration:none;text-indent:0;text-shadow:none;text-transform:none;visibility:visible;white-space:normal;word-spacing:normal}.fb_reset>div{overflow:hidden}.fb_link img{border:none}
.fb_dialog{background:rgba(82, 82, 82, .7);position:absolute;top:-10000px;z-index:10001}.fb_reset .fb_dialog_legacy{overflow:visible}.fb_dialog_advanced{padding:10px;-moz-border-radius:8px;-webkit-border-radius:8px;border-radius:8px}.fb_dialog_content{background:#fff;color:#333}.fb_dialog_close_icon{background:url(http://static.ak.fbcdn.net/rsrc.php/v2/yq/r/IE9JII6Z1Ys.png) no-repeat scroll 0 0 transparent;_background-image:url(http://static.ak.fbcdn.net/rsrc.php/v2/yL/r/s816eWC-2sl.gif);cursor:pointer;display:block;height:15px;position:absolute;right:18px;top:17px;width:15px}.fb_dialog_mobile .fb_dialog_close_icon{top:5px;left:5px;right:auto}.fb_dialog_padding{background-color:transparent;position:absolute;width:1px;z-index:-1}.fb_dialog_close_icon:hover{background:url(http://static.ak.fbcdn.net/rsrc.php/v2/yq/r/IE9JII6Z1Ys.png) no-repeat scroll 0 -15px transparent;_background-image:url(http://static.ak.fbcdn.net/rsrc.php/v2/yL/r/s816eWC-2sl.gif)}.fb_dialog_close_icon:active{background:url(http://static.ak.fbcdn.net/rsrc.php/v2/yq/r/IE9JII6Z1Ys.png) no-repeat scroll 0 -30px transparent;_background-image:url(http://static.ak.fbcdn.net/rsrc.php/v2/yL/r/s816eWC-2sl.gif)}.fb_dialog_loader{background-color:#f6f7f8;border:1px solid #606060;font-size:24px;padding:20px}.fb_dialog_top_left,.fb_dialog_top_right,.fb_dialog_bottom_left,.fb_dialog_bottom_right{height:10px;width:10px;overflow:hidden;position:absolute}.fb_dialog_top_left{background:url(http://static.ak.fbcdn.net/rsrc.php/v2/ye/r/8YeTNIlTZjm.png) no-repeat 0 0;left:-10px;top:-10px}.fb_dialog_top_right{background:url(http://static.ak.fbcdn.net/rsrc.php/v2/ye/r/8YeTNIlTZjm.png) no-repeat 0 -10px;right:-10px;top:-10px}.fb_dialog_bottom_left{background:url(http://static.ak.fbcdn.net/rsrc.php/v2/ye/r/8YeTNIlTZjm.png) no-repeat 0 -20px;bottom:-10px;left:-10px}.fb_dialog_bottom_right{background:url(http://static.ak.fbcdn.net/rsrc.php/v2/ye/r/8YeTNIlTZjm.png) no-repeat 0 -30px;right:-10px;bottom:-10px}.fb_dialog_vert_left,.fb_dialog_vert_right,.fb_dialog_horiz_top,.fb_dialog_horiz_bottom{position:absolute;background:#525252;filter:alpha(opacity=70);opacity:.7}.fb_dialog_vert_left,.fb_dialog_vert_right{width:10px;height:100%}.fb_dialog_vert_left{margin-left:-10px}.fb_dialog_vert_right{right:0;margin-right:-10px}.fb_dialog_horiz_top,.fb_dialog_horiz_bottom{width:100%;height:10px}.fb_dialog_horiz_top{margin-top:-10px}.fb_dialog_horiz_bottom{bottom:0;margin-bottom:-10px}.fb_dialog_iframe{line-height:0}.fb_dialog_content .dialog_title{background:#6d84b4;border:1px solid #3a5795;color:#fff;font-size:14px;font-weight:bold;margin:0}.fb_dialog_content .dialog_title>span{background:url(http://static.ak.fbcdn.net/rsrc.php/v2/yd/r/Cou7n-nqK52.gif) no-repeat 5px 50%;float:left;padding:5px 0 7px 26px}body.fb_hidden{-webkit-transform:none;height:100%;margin:0;overflow:visible;position:absolute;top:-10000px;left:0;width:100%}.fb_dialog.fb_dialog_mobile.loading{background:url(http://static.ak.fbcdn.net/rsrc.php/v2/ya/r/3rhSv5V8j3o.gif) white no-repeat 50% 50%;min-height:100%;min-width:100%;overflow:hidden;position:absolute;top:0;z-index:10001}.fb_dialog.fb_dialog_mobile.loading.centered{max-height:590px;min-height:590px;max-width:500px;min-width:500px}#fb-root #fb_dialog_ipad_overlay{background:rgba(0, 0, 0, .45);position:absolute;left:0;top:0;width:100%;min-height:100%;z-index:10000}#fb-root #fb_dialog_ipad_overlay.hidden{display:none}.fb_dialog.fb_dialog_mobile.loading iframe{visibility:hidden}.fb_dialog_content .dialog_header{-webkit-box-shadow:white 0 1px 1px -1px inset;background:-webkit-gradient(linear, 0% 0%, 0% 100%, from(#738ABA), to(#2C4987));border-bottom:1px solid;border-color:#1d4088;color:#fff;font:14px Helvetica, sans-serif;font-weight:bold;text-overflow:ellipsis;text-shadow:rgba(0, 30, 84, .296875) 0 -1px 0;vertical-align:middle;white-space:nowrap}.fb_dialog_content .dialog_header table{-webkit-font-smoothing:subpixel-antialiased;height:43px;width:100%}.fb_dialog_content .dialog_header td.header_left{font-size:12px;padding-left:5px;vertical-align:middle;width:60px}.fb_dialog_c
.fb_iframe_widget{display:inline-block;position:relative}.fb_iframe_widget span{display:inline-block;position:relative;text-align:justify}.fb_iframe_widget iframe{position:absolute}.fb_iframe_widget_fluid_desktop,.fb_iframe_widget_fluid_desktop span,.fb_iframe_widget_fluid_desktop iframe{max-width:100%}.fb_iframe_widget_fluid_desktop iframe{min-width:220px;position:relative}.fb_iframe_widget_lift{z-index:1}.fb_hide_iframes iframe{position:relative;left:-10000px}.fb_iframe_widget_loader{position:relative;display:inline-block}.fb_iframe_widget_fluid{display:inline}.fb_iframe_widget_fluid span{width:100%}.fb_iframe_widget_loader iframe{min-height:32px;z-index:2;zoom:1}.fb_iframe_widget_loader .FB_Loader{background:url(http://static.ak.fbcdn.net/rsrc.php/v2/y9/r/jKEcVPZFk-2.gif) no-repeat;height:32px;width:32px;margin-left:-16px;position:absolute;left:50%;z-index:4}</style></head>
<body style="zoom: 100%;">
<div id="mula-timer" class="disabled"><table><tbody><tr><td>Load</td><td>2451ms</td></tr><tr><td>Last render</td><td>2663ms</td></tr><tr><td>Average render</td><td>2663ms</td></tr><tr><td>Renders</td><td>1</td></tr><tr><td>Re-renders</td><td>0</td></tr></tbody></table></div>
<div id="layout">
<div id="menu-container"><div><div id="menu-link" class="menu-link"><a class="spa-link clickable" href="http://sc5.io/"><img width="60" height="60" src="./react_files/sc5logo-fat.svg" alt="SC5"></a><div class="menu-link-button clickable"><span class="icon-menu">Menu</span></div></div><div id="menu" class="menu"><ul><li><a class="spa-link clickable" href="http://sc5.io/"><img width="60" height="60" class="icon-sc5" alt="SC5" src="./react_files/sc5logo-fat.svg"></a></li><li><a class="spa-link clickable selected" href="http://sc5.io/posts/first_post">Blog</a></li><li><a class="spa-link clickable" href="http://sc5.io/pages/solutions">Our Solutions</a></li><li><a class="spa-link clickable" href="http://sc5.io/pages/careers">Careers</a></li><li><a class="spa-link clickable" href="http://sc5.io/pages/get-in-touch">Get In Touch</a></li></ul><div class="menu-additional-content"><a class="clickable" href="https://twitter.com/sc5io" target="_blank"><span class="icon-twitter"></span></a><a class="clickable" href="https://www.facebook.com/sc5.io" target="_blank"><span class="icon-face"></span></a><a class="clickable" href="https://www.linkedin.com/company/sc5" target="_blank"><span class="icon-linkedin2"></span></a></div></div></div></div>
<div id="content-container">
<div id="main">
<div id="contact-us"><a href="http://sc5.io/posts/using-reacts-jsx-with-coffeescript-and-sublime-text#" class="contact-title">
<div class="contact-heading">Contact Us</div>
</a>
<form class="contact-form" action="http://sc5.io/posts/using-reacts-jsx-with-coffeescript-and-sublime-text#">
<p class="feedback"></p>
<input name="name" type="text" placeholder="Name" required="">
<input name="email" type="email" placeholder="Email" required="">
<textarea name="message" rows="4" placeholder="Message"></textarea>
<input type="submit" value="Send message">
<input type="button" value="Subscribe to SC5 News!">
</form></div><div id="post-page" class="page light"><div class="page-content">
<div class="page-wrapper">
<div class="posts-container" style="min-height: 968px">
<div class="item current" id="wp-post-2314" style="min-height: 968px" data-href="/posts/using-reacts-jsx-with-coffeescript-and-sublime-text">
<div class="item-container">
<div class="content">
<div class="header">
<h1 class="post-subhead">Using React's JSX with CoffeeScript and Sublime Text</h1>
<div class="meta"><span class="author">Lari Hoppula | </span>
<span class="time">
<time datetime="[object Object]">
<span class="month">Jun</span>
<span class="day">10</span>
<span class="year">2014</span>
</time>
</span>
</div>
<div class="social-buttons"><!--<div class="fb-like" data-href="http://sc5.io/posts/using-reacts-jsx-with-coffeescript-and-sublime-text" data-layout="button_count" data-action="like" data-show-faces="true" data-share="true"></div>--></div>
</div>
<!-- <div class="featured-image"><img src="" alt="Featured image" /></div> -->
<div class="item-content"><p><a href="./react_files/blog-wp-content-uploads-2014-06-react.png" data-lightbox="image"><img src="./react_files/blog-wp-content-uploads-2014-06-react$1120s.png" alt="react" width="250" height="250" class="mula-adaptive alignnone size-full wp-image-2339"></a>
</p><p style="color: #000000;">
<a style="color: #205caa;" href="http://facebook.github.io/react/" title="React.js">React.js</a> has been gaining ground lately in JavaScript world, replacing many libraries traditionally used for view manipulation. It embraces one-way data flow and separation of view components data (props) and its internal state. For more detailed explanation of Reacts strengths, <a style="color: #205caa;" href="https://www.youtube.com/watch?v=DgVS-zXgMTk">check out Pete Hunts excellent presentation from JSConf.Asia 2013</a> and <a style="color: #205caa;" href="http://facebook.github.io/react/docs/thinking-in-react.html">Thinking in React article</a> from Reacts docs.</p>
<p style="color: #000000;">
<a style="color: #205caa;" href="http://facebook.github.io/react/docs/jsx-in-depth.html" title="JSX">JSX</a> is XML-syntaxed markup that is embedded to React components render method. React JSX compiler transforms embedded JSX markup to React.DOM.* calls in compiled JavaScript. Writing JSX is easy for anyone who knows HTML and its certainly much easier to grasp than writing nested React.DOM.* calls manually.</p>
<h2 id="problem-coffeescript-jsx-dont-play-well-with-each-other" style="font-weight: 300; color: #000000;">Problem: CoffeeScript + JSX dont play well with each other</h2>
<p style="color: #000000;">Until recently, you were forced to write your CoffeeScript React component renders by&nbsp;<a style="color: #205caa;" href="http://www.rigelgroupllc.com/blog/2013/11/19/using-reactjs-with-coffeescript/">shelling out to JS with backticks</a>&nbsp;or&nbsp;<a style="color: #205caa;" href="http://blog.vjeux.com/2013/javascript/react-coffeescript.html">desugaring React.DOM to create lightweight DSL</a>.</p>
<p style="color: #000000;">Luckily for us wanting the real deal,&nbsp;<a style="color: #205caa;" href="https://github.com/jsdf">James Friend</a>&nbsp;has created&nbsp;<a style="color: #205caa;" href="https://github.com/jsdf/coffee-react-transform">CoffeeScript transformer for JSX</a>&nbsp;which allows you to write that nicely formatted JSX also in your .coffee files.</p>
<p style="color: #000000;"><a style="color: #205caa;" href="https://github.com/jsdf/coffee-react-transform">coffee-react-transform</a>&nbsp;can be used through&nbsp;<a style="color: #205caa;" href="https://github.com/jsdf/coffee-react-transform#cli">CLI</a>&nbsp;or&nbsp;<a style="color: #205caa;" href="https://github.com/jsdf/coffee-react-transform#api">API</a>. If you want CoffeeScript executable that understands CJSX, you can use&nbsp;<a style="color: #205caa;" href="https://github.com/jsdf/coffee-react">coffee-react</a>&nbsp;from the same author.</p>
<h2 id="requiring-cjsxified-coffee-files-in-node" style="font-weight: 300; color: #000000;">Requiring CJSXified .coffee files in node</h2>
<p style="color: #000000;">If you want to use the vanilla coffee executable to require CJSX enhanced files, you can use&nbsp;<a style="color: #205caa;" href="https://github.com/SimonDegraeve/node-cjsx">node-cjsx</a>&nbsp;module, which transparently compiles CJSX with&nbsp;<a style="color: #205caa;" href="https://github.com/jsdf/coffee-react-transform">coffee-react-transform</a>&nbsp;before second compilation step with regular coffee binary. Just add&nbsp;<code>require('node-cjsx').transform()</code>&nbsp;to your app and youre good to go.</p>
<h2 id="sublime-text" style="font-weight: 300; color: #000000;">Sublime Text</h2>
<p style="color: #000000;">If you use&nbsp;<a style="color: #205caa;" href="http://www.sublimetext.com/">Sublime Text</a>, theres a way to make working with CJSX much more enjoyable.</p>
<p style="color: #000000;">First, you can install&nbsp;<a style="color: #205caa;" href="https://github.com/reactjs/sublime-react">sublime-react</a>&nbsp;which just had&nbsp;<a style="color: #205caa;" href="https://github.com/reactjs/sublime-react/pull/9">CJSX support committed&nbsp;in</a> by&nbsp;<a style="color: #205caa;" href="https://github.com/tgriesser">Tim Griesser</a>. It provides syntax highlighting and&nbsp;<a style="color: #205caa;" href="https://github.com/reactjs/sublime-react#documentation-of-available-snippets-jsx">autocompletion snippets</a>&nbsp;for CJSX.</p>
<p style="color: #000000;">Second, you can change&nbsp;<a style="color: #205caa;" href="https://github.com/aponxi/sublime-better-coffeescript">Better CoffeeScript</a>&nbsp;plugin to use previously mentioned&nbsp;<a style="color: #205caa;" href="https://github.com/jsdf/coffee-react">coffee-react</a>&nbsp;as its coffee executable. Easy way to do that is to create symbolic link from your cjsx binary (e.g.&nbsp;<em>~/.nvm/v0.10.28/bin/cjsx</em>) to<em>~/bin/coffee</em>&nbsp;and setting&nbsp;<em>~/bin</em>&nbsp;as&nbsp;<strong><code>"binDir"</code></strong>&nbsp;in&nbsp;<em>CoffeeScript.sublime-settings</em>. Also remember to change<strong>`“envPATH”</strong>&nbsp;in that same settings file to a directory containing node executable (e.g.&nbsp;<em>~/nvm/v0.10.28/bin</em>).</p>
<p style="color: #000000;"><strong>NOTE:</strong>&nbsp;<em>Replace ~ with your home dir, so e.g. ~/bin becomes /Users/hoppula/bin, Sublime does not seem to understand ~/ in config files</em>.</p>
<p style="color: #000000;">Now youll get a nice preview of compiled JavaScript when you press&nbsp;<code>ALT+SHIFT+D</code>&nbsp;while editing your components .coffee file.</p>
<h3 id="cjsx-to-javascript-conversion-example" style="font-weight: 300; color: #000000;">CJSX to JavaScript conversion example</h3>
<h5 id="coffeescript-source" style="font-weight: 300; color: #000000;">CoffeeScript source</h5>
<div class="highlight" style="color: #000000;">
<pre><code class="coffeescript"><span class="c1" style="font-style: italic; color: #999988;"># @cjsx React.DOM</span>
<span class="nv" style="color: #008080;">React = </span><span class="nx">require</span> <span class="s" style="color: #dd1144;">'react'</span>
<span class="nv" style="color: #008080;">Team = </span><span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span>
<span class="nv" style="color: #008080;">render: </span><span class="nf" style="font-weight: bold; color: #990000;">-&gt;</span>
<span class="o" style="font-weight: bold;">&lt;</span><span class="nx">div</span> <span class="nx">className</span><span class="o" style="font-weight: bold;">=</span><span class="s" style="color: #dd1144;">"team"</span><span class="o" style="font-weight: bold;">&gt;</span>
<span class="o" style="font-weight: bold;">&lt;</span><span class="nx">div</span><span class="o" style="font-weight: bold;">&gt;</span><span class="p">{</span><span class="nx">@props</span><span class="p">.</span><span class="nx">team</span><span class="p">.</span><span class="nx">name</span><span class="p">}</span><span class="o" style="font-weight: bold;">&lt;/</span><span class="nx">div</span><span class="o" style="font-weight: bold;">&gt;</span>
<span class="o" style="font-weight: bold;">&lt;</span><span class="nx">div</span><span class="o" style="font-weight: bold;">&gt;</span><span class="p">{</span><span class="nx">@props</span><span class="p">.</span><span class="nx">team</span><span class="p">.</span><span class="nx">city</span><span class="p">}</span><span class="o" style="font-weight: bold;">&lt;/</span><span class="nx">div</span><span class="o" style="font-weight: bold;">&gt;</span>
<span class="o" style="font-weight: bold;">&lt;/</span><span class="nx">div</span><span class="o" style="font-weight: bold;">&gt;</span>
<span class="nv" style="color: #008080;">module.exports = </span><span class="nx">Team</span>
</code></pre>
</div>
<h5 id="compiled-javascript" style="font-weight: 300; color: #000000;">Compiled JavaScript</h5>
<div class="highlight" style="color: #000000;">
<pre><code class="javascript"><span class="kd" style="font-weight: bold;">var</span> <span class="nx">React</span><span class="p">,</span> <span class="nx">Team</span><span class="p">;</span>
<span class="nx">React</span> <span class="o" style="font-weight: bold;">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1" style="color: #dd1144;">'react'</span><span class="p">);</span>
<span class="nx">Team</span> <span class="o" style="font-weight: bold;">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createClass</span><span class="p">({</span>
<span class="nx">render</span><span class="o" style="font-weight: bold;">:</span> <span class="kd" style="font-weight: bold;">function</span><span class="p">()</span> <span class="p">{</span>
<span class="k" style="font-weight: bold;">return</span> <span class="nx">React</span><span class="p">.</span><span class="nx">DOM</span><span class="p">.</span><span class="nx">div</span><span class="p">({</span>
<span class="s2" style="color: #dd1144;">"className"</span><span class="o" style="font-weight: bold;">:</span> <span class="s2" style="color: #dd1144;">"team"</span>
<span class="p">},</span> <span class="nx">React</span><span class="p">.</span><span class="nx">DOM</span><span class="p">.</span><span class="nx">div</span><span class="p">(</span><span class="kc" style="font-weight: bold;">null</span><span class="p">,</span> <span class="k" style="font-weight: bold;">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">team</span><span class="p">.</span><span class="nx">name</span><span class="p">),</span>
<span class="nx">React</span><span class="p">.</span><span class="nx">DOM</span><span class="p">.</span><span class="nx">div</span><span class="p">(</span><span class="kc" style="font-weight: bold;">null</span><span class="p">,</span> <span class="k" style="font-weight: bold;">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">team</span><span class="p">.</span><span class="nx">city</span><span class="p">));</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o" style="font-weight: bold;">=</span> <span class="nx">Team</span><span class="p">;</span>
</code></pre>
</div>
<h2 id="browserify" style="font-weight: 300; color: #000000;">Browserify</h2>
<p style="color: #000000;"><a style="color: #205caa;" href="https://github.com/jsdf">James Friend</a>&nbsp;has also written&nbsp;<a style="color: #205caa;" href="https://github.com/jsdf/coffee-reactify">coffee-reactify</a>&nbsp;browserify plugin, so you can easily use that same view code when rendering on server and in browser.</p>
<p><em>This blog post is an extended version of story that was originally published on <a href="http://lari.hoppula.com/2014/06/10/using-reacts-jsx-with-coffeescript-and-sublime-text/">my personal blog</a></em>.</p>
</div>
</div>
</div>
</div>
</div>
<div class="left-menu">
<div class="left-menu-inner">
<div id="post-list">
<h1>More from our blog</h1>
<a class="spa-link clickable immediate frombottom " href="http://sc5.io/posts/nokian-ja-alcatel-lucentin-fuusio-ennakoi-iotn-tulemista" data-id="4474">Nokian ja Alcatel-Lucentin fuusio ennakoi IoT:n tulemista</a>
<a class="spa-link clickable immediate frombottom " href="http://sc5.io/posts/pelillinen-strategiaopas-verkkoon-kuukaudessa" data-id="4461">Pelillinen strategiaopas verkkoon kuukaudessa</a>
<a class="spa-link clickable immediate frombottom " href="http://sc5.io/posts/tuleeko-alykelloista-oikea-sovellusalusta" data-id="4427">Tuleeko älykelloista oikea sovellusalusta?</a>
<a class="spa-link clickable immediate frombottom " href="http://sc5.io/posts/sc5sta-stadin-atk-apu" data-id="4406">SC5:stä Stadin ATK-apu!</a>
<a class="spa-link clickable immediate frombottom " href="http://sc5.io/posts/miten-sossit-digitaalisen-liiketoiminnan-rakentamisen" data-id="4386">Miten sössit digitaalisen liiketoiminnan rakentamisen</a>
<a class="spa-link clickable immediate frombottom " href="http://sc5.io/posts/pikaviesteista-syntyy-uusi-myyntikanava" data-id="4283">Pikaviesteistä syntyy uusi myyntikanava</a>
<a class="spa-link clickable immediate frombottom " href="http://sc5.io/posts/kuukausien-sykleista-tunteihin-full-stack-kehityksella" data-id="4301">Kuukausien sykleistä tunteihin Full Stack -kehityksellä</a>
<a class="older" href="http://sc5.io/posts/using-reacts-jsx-with-coffeescript-and-sublime-text#" data-id="4474">Older posts</a>
</div>
</div>
</div>
</div>
</div>
</div></div>
</div>
<footer id="footer"><section class="footer-contact"><a href="http://sc5.io/pages/get-in-touch">Get in touch</a> | <a href="http://sc5.io/pages/privacy">Privacy policy</a>
</section></footer>
</div>
<script data-main="/app/main-0.1.1.js" src="./react_files/require-0.1.1.js" async="" defer=""></script>
<!-- Start of Async HubSpot Analytics Code -->
<script type="text/javascript">
(function(d,s,i,r) {
if (d.getElementById(i)){return;}
var n=d.createElement(s),e=d.getElementsByTagName(s)[0];
n.id=i;n.src='//js.hs-analytics.net/analytics/'+(Math.ceil(new Date()/r)*r)+'/469635.js';
e.parentNode.insertBefore(n, e);
})(document,"script","hs-analytics",300000);
</script>
<!-- End of Async HubSpot Analytics Code -->
<!-- Google analytics and PageAd codes -->
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-27451947-1', 'auto');
</script>
<script type="text/javascript">
/* <![CDATA[ */
var google_conversion_id = 971659824;
var google_custom_params = window.google_tag_params;
var google_remarketing_only = true;
/* ]]> */
</script>
<script type="text/javascript" src="http://www.googleadservices.com/pagead/conversion.js"></script>
<div id="fb-root" class=" fb_reset"><div style="position: absolute; top: -10000px; height: 0px; width: 0px;"><div><iframe name="fb_xdm_frame_http" frameborder="0" allowtransparency="true" allowfullscreen="true" scrolling="no" id="fb_xdm_frame_http" aria-hidden="true" title="Facebook Cross Domain Communication Frame" tabindex="-1" src="./react_files/KvoNGODIqPG.html" style="border: none;"></iframe><iframe name="fb_xdm_frame_https" frameborder="0" allowtransparency="true" allowfullscreen="true" scrolling="no" id="fb_xdm_frame_https" aria-hidden="true" title="Facebook Cross Domain Communication Frame" tabindex="-1" src="./react_files/KvoNGODIqPG(1).html" style="border: none;"></iframe></div></div><div style="position: absolute; top: -10000px; height: 0px; width: 0px;"><div></div></div></div>
<script>
window.fbAsyncInit = function() {
FB.init({
appId : '391511784314846',
xfbml : true,
version : 'v2.1'
});
};
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
</script>
<noscript>
&lt;div style="display:inline;"&gt;
&lt;img height="1" width="1" style="border-style:none;" alt="" src="//googleads.g.doubleclick.net/pagead/viewthroughconversion/971659824/?value=0&amp;amp;guid=ON&amp;amp;script=0"&gt;
&lt;/div&gt;
</noscript>
<style>.social-buttons,.icon-twitter,[href^="https://facebook.com/sharer.php?"],[href^="http://www.linkz.it/"],[href^="http://www.linkedin.com/shareArticle?"],[href^="http://www.linkbucks.com/referral/"],[href^="https://www.facebook.com/sharer/sharer.php?u="],[href^="https://www.facebook.com/sharer.php?"],[href^="http://www.facebook.com/sharer/sharer.php?"],[href^="http://www.facebook.com/sharer.php?"],[href^="http://www.facebook.com/share.php?u="],[href^="http://www.faceporn.net/free?"],[href^="https://twitter.com/share?"],[href^="https://twitter.com/intent/tweet?"],[href^="https://twitter.com/intent/retweet?tweet_id"],[href^="https://twitter.com/intent/follow?"],[href^="http://twitter.com/share?"],[href^="http://twitter.com/intent/tweet?"],[href^="http://twitter.com/intent/tweet/?url="],[href^="http://twitter.com/home?"],[href^="http://twitter.com/home/?"],[href^="http://twitter.com/?status="]
{display:none !important;}</style><div id="lightboxOverlay" class="lightboxOverlay" style="width: 1905px; height: 4081px; display: block;"></div><div id="lightbox" class="lightbox" style="display: block; top: 50px; left: 0px;"><div class="lb-outerContainer" style="width: 258px; height: 258px;"><div class="lb-container"><img class="lb-image" src="./react_files/blog-wp-content-uploads-2014-06-react.png" style="display: block; width: 250px; height: 250px;"><div class="lb-nav" style="display: block;"><a class="lb-prev" href="" style="display: none;"></a><a class="lb-next" href="" style="display: none;"></a></div><div class="lb-loader" style="display: none;"><a class="lb-cancel"></a></div></div></div><div class="lb-dataContainer" style="display: block; width: 258px;"><div class="lb-data"><div class="lb-details"><span class="lb-caption" style="display: none;"></span><span class="lb-number" style="display: none;"></span></div><div class="lb-closeContainer"><a class="lb-close"></a></div></div></div></div></body></html>