Skip to main content
Redhat Developers  Logo
  • Products

    Platforms

    • Red Hat Enterprise Linux
      Red Hat Enterprise Linux Icon
    • Red Hat AI
      Red Hat AI
    • Red Hat OpenShift
      Openshift icon
    • Red Hat Ansible Automation Platform
      Ansible icon
    • View All Red Hat Products

    Featured

    • Red Hat build of OpenJDK
    • Red Hat Developer Hub
    • Red Hat JBoss Enterprise Application Platform
    • Red Hat OpenShift Dev Spaces
    • Red Hat OpenShift Local
    • Red Hat Developer Sandbox

      Try Red Hat products and technologies without setup or configuration fees for 30 days with this shared Openshift and Kubernetes cluster.
    • Try at no cost
  • Technologies

    Featured

    • AI/ML
      AI/ML Icon
    • Linux
      Linux Icon
    • Kubernetes
      Cloud icon
    • Automation
      Automation Icon showing arrows moving in a circle around a gear
    • View All Technologies
    • Programming Languages & Frameworks

      • Java
      • Python
      • JavaScript
    • System Design & Architecture

      • Red Hat architecture and design patterns
      • Microservices
      • Event-Driven Architecture
      • Databases
    • Developer Productivity

      • Developer productivity
      • Developer Tools
      • GitOps
    • Automated Data Processing

      • AI/ML
      • Data Science
      • Apache Kafka on Kubernetes
    • Platform Engineering

      • DevOps
      • DevSecOps
      • Ansible automation for applications and services
    • Secure Development & Architectures

      • Security
      • Secure coding
  • Learn

    Featured

    • Kubernetes & Cloud Native
      Openshift icon
    • Linux
      Rhel icon
    • Automation
      Ansible cloud icon
    • AI/ML
      AI/ML Icon
    • View All Learning Resources

    E-Books

    • GitOps Cookbook
    • Podman in Action
    • Kubernetes Operators
    • The Path to GitOps
    • View All E-books

    Cheat Sheets

    • Linux Commands
    • Bash Commands
    • Git
    • systemd Commands
    • View All Cheat Sheets

    Documentation

    • Product Documentation
    • API Catalog
    • Legacy Documentation
  • Developer Sandbox

    Developer Sandbox

    • Access Red Hat’s products and technologies without setup or configuration, and start developing quicker than ever before with our new, no-cost sandbox environments.
    • Explore Developer Sandbox

    Featured Developer Sandbox activities

    • Get started with your Developer Sandbox
    • OpenShift virtualization and application modernization using the Developer Sandbox
    • Explore all Developer Sandbox activities

    Ready to start developing apps?

    • Try at no cost
  • Blog
  • Events
  • Videos

Have some CoffeeScript with your React

June 19, 2014
Samuel Mendenhall
Related products:
Developer Tools

Share:

    In my continual search for the ever more efficient and pragmatic Javascript UI framework, I've stumbled upon React, but not just React, the special combination of React, Coffeescript, and RequireJS.

    JSX is the more elegant way to compose the DOM within React classes, however, it does require an additional compile step, and there is a bit of added complexity when integrating with RequireJS.

    It would be hard to give up JSX and go back to building the DOM with plain javascript, the syntax isn't so elegant, and it gets quite busy. Coffeescript, at first thought, may seem like a lesser alternative; I will propose, however, that it may just be equal to more practical than even JSX.

    Defining the DOM

    Let's take a look at the three ways to write an unordered list in React.

    JSX:

    <ul>
      <li>Item 1</li>
      <li>Item 2</li>
    </ul>

    Javascript:

    React.DOM.ul({}, [
      React.DOM.li({}, 'Item 1'),
      React.DOM.li({}, 'Item 2'),
    ])

    Coffeescript:

    (ul {}, [
      (li {}, ['Item 1'])
      (li {}, ['Item 2'])
    ])

    Coffeescript w/Lodash:

    (ul {}, _.map ['Item 1', 'Item 2'], (item) -> (li {}, [item]))

    All of these are identical.

    The CoffeeScript version displays some lisp-like and jade-like feel to it. Not needing to close the tags feels satisfying, and being directly in code feels good and does open up a more consistent way to embed logic alongside the DOM. In JSX, it isn't much of a burden, but I do see a benefit of going pure CoffeeScript.

    By not closing I mean:

    (li {}, []) versus <li></li>

    Another example of how much more compact CoffeeScript can be:

    JSX:

    render: function() {
        var text = this.state.liked ? 'like' : 'unlike';
        return (
          <p onClick={this.handleClick}>
            You {text} this. Click to toggle.
          </p>
        );
    }

    CoffeeScript:

    render: ->
      text = if @state.liked then 'like else 'unlike
      (p {onClick=@handleClick}, ["You #{text} this. Click to toggle."])

    You could further embed the text ternary logic in the #{}, but that gets a bit messy.

    Let's unpack what is really going on in CoffeeScript with a (elem {}, [])

    (elem {}, []) would really translate to elem({}, [])

    Looking at the Chrome console at the a de-structured element:

    function (props, children) {
      var instance = new Constructor();
      instance.construct.apply(instance, arguments);
      return instance;
    }

    In other words, any element defined through the following construct will be a React.DOM function that takes props and children as arguments:

    {ul, li, div, h4} = React.DOM

    This is just what you would expect from the regular React.DOM.* way of composing the DOM in javascript. The code above is CoffeeScript's convenient way of de-structuring objects from right to left, this is also proposed in the ECMAScript 6 Specification.

    RequireJS with CoffeeScript

    The conciseness and compactness of the combination of CoffeeScript and RequireJS are gratifying as a developer. This particular combination has nothing to do with React, but it will greatly augment the cleanness and organization of your project, be it React, or whatnot.

    The first order of business here is to define a function to let us mix in any arbitrary properties to any class prototype:

    # The code of the include was inspired from https://arcturo.github.io/library/coffeescript/03_classes.html
    # Since the default return type is an object, and no return keyword is necessary, this bit of code effectively returns
    # an object containing a single 'include' function field. The corresponding js is over double in size.
    # See the extend function in the above link for extending objects, not classes.
    # Alternatively, see https://coffeescriptcookbook.com/chapters/classes_and_objects/mixins
    define 'moduleMixin', [], () ->
      include: (obj) ->
        for key, value of obj when key not in ['extended', 'included']
          # Assign properties to the prototype
          @::[key] = value
        obj.included?.apply(@)
        @

    I'm not going to go in-depth into RequireJS other than to mention that it can be syntactically verbose, however it is simplified by CoffeeScript. The basic define function call is:

    # All arguments are optional
    define module name, [dependencies], (dependency names) -&gt;
      # code goes here

    Create the Mixins

    Now that we have the basic building blocks for mixins, let's mixin.

    Define a function to add numbers:

    define 'sumMixin', [], () ->
      sum: (a, b) -> a + b

    And now a function to multiply numbers:

    define 'multMixin', [], () ->
      mult: (a, b) -> a * b

    Simple enough right. Including those in any other defined class is just as easy:

    define 'someController', ['moduleMixin', 'sumMixin', 'multMixin'], (Module, SumMixin, MultMixin) ->
      class SomeController extends Module
        # Make sure the mixin functions and variables are included to 'this' class
        @include.call(@, SumMixin)
        @include.call(@, MultMixin)
        constructor: () -> undefined

    The above is saying this. Define a new module named 'someController' (You don't need the name if you want to reference a js file on the filesystem), depending on the given dependencies, and return a class SomeController which mixes in the SumMixin and MultMixin functions.

    As you can probably tell at this point, the ability to define and include any mixin opens up a world of possibilities in terms of refactoring your existing javascript code. You can pick and choose which functionality you want to mix into your javascript classes or objects.

    Create the React class

    The final piece of this example would be defining the React view and injecting the above controller.

    require ['someController'], (SomeController) ->
      {ul, li, div, h4} = React.DOM
    
      controller = new SomeController()
    
      ExampleView = React.createClass
        render: ->
          (div {}, [
            (h4 {}, ['Requirejs + Coffeescript + React Example'])
            (ul {}, [
              (li {}, ['Sum of 1 and 2 is: ' + @props.sum(1, 2)]),
              (li {}, ['Mult of 5 and 6 is: ' + @props.mult(5, 6)]),
            ])
          ])
    
      opts =
        sum: controller.sum
        mult: controller.mult
    
      React.renderComponent (ExampleView opts), document.body

    Note that I'm using require vs define here purely for this example. I am not defining another module, just requiring existing modules. In the real world, you will probably want your React view components also defined as modules so you can require/depend on them in other components. That is a very common model.

    The readability of this approach is fantastic, the code is clean, and there is no need for the translated JSX layer. If you haven't tried this combination I would definitely encourage you to do so.

    Example Code
    For the full example from the above code please see:

    Last updated: February 7, 2024

    Recent Posts

    • A deep dive into Apache Kafka's KRaft protocol

    • Staying ahead of artificial intelligence threats

    • Strengthen privacy and security with encrypted DNS in RHEL

    • How to enable Ansible Lightspeed intelligent assistant

    • Why some agentic AI developers are moving code from Python to Rust

    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Products

    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform

    Build

    • Developer Sandbox
    • Developer Tools
    • Interactive Tutorials
    • API Catalog

    Quicklinks

    • Learning Resources
    • E-books
    • Cheat Sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site Status Dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit
    © 2025 Red Hat

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility

    Report a website issue