Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

React.js at Cortex

How Cortex used Facebook's React.js and Flux architecture to turn our webapp into a super-fast single-page application.

  • Be the first to comment

React.js at Cortex

  1. 1. How we use React.js A case study in completely re-implementing your UI in one month Iron Yard Crystal City - Tuesday April 7, 2015
  2. 2. Hi, I’m Geoff • CTO and Cofounder at Cortex • Began career as an analyst and project manager • Began development as a hobby (interested in baseball stats) • Fell in love with Ruby after initial flirtation with PHP • Started Five Tool Development, a web development agency
  3. 3. What does Cortex do? • Our application provides commercial building operators and engineers with minute-to-minute recommendations about energy use and live data from hundreds of sensors and meters • Our first building saved half a million dollars in energy costs during their first year using Cortex • 95% of our customer use is through mobile apps. We deliver a responsive web application in a WebView container to iOS and Android
  4. 4. What we’re going to talk about • Super-fast overview of what React is • How we used React to dramatically improve Cortex • Even faster overview of Flux • Questions (feel free to stop me any time)
  5. 5. Problem Building engineers frequently work in spaces with no network connectivity. They expect to be able to get their data everywhere.
  6. 6. Complication Need to support three platforms (web, iOS, Android) with limited resources. We have already invested hundreds of hours in a first-class HTML- based interface.
  7. 7. The Plan Turn our webapp into a persistently-open single-page application (SPA). Users will be on the same page all the time, so the application will never reload in the browser. Our application will fetch and cache data when the network is available, and present it even when the network is unavailable.
  8. 8. What is MVC? Source: Google (https://developer.chrome.com/apps/app_frameworks)
  9. 9. Lots of JavaScript MVC Frameworks Compared to Ruby, JavaScript is the Wild (Wild) West. Space is less mature, but filled with really interesting new innovations and ideas. Cutting-edge solutions, but not a lot of consensus around which are the best yet. Source: James T. West
  10. 10. Backbone • Created by Jeremy Ashkenas from the New York Times visualizations group (he built Coffeescript, Underscore.js) • Early pioneer in JavaScript MVC frameworks • Focus on data sync between browser and server-based API, leaves view/presentation layer up to developer
  11. 11. Ember • Created by Yehuda Katz (of Rails- and jQuery-core fame) and Tom Dale • Uses two-way data binding • Very opinionated, does things “the Ember Way” • Explicitly for single-page apps • Has awesome routing • Liked by many Rails developers
  12. 12. Angular • Developed at Google • Uses two-way data binding • Less opinionated than Ember, which means it is more flexible, but also requires you to do more heavy lifting yourself • Not just for SPAs • Extends HTML with custom attributes
  13. 13. React • Developed at Facebook • Unidirectional flow of data (one-way binding) • Re-renders everything when something changes, uses a “virtual DOM” to calculate differences • Can be implemented in small pieces, does not require full-scale use across application • Younger than previous options, rapidly growing
  14. 14. With or without you (by “you”, I mean a network) • Cache data in browser using localStorage API • Always be on the same page, never reload the page due to user clicks • Give friendly messages when network is unavailable Source: The Edge
  15. 15. The need for speed • Context changes should be snappy • Pre-fetch data the user will likely want and put it into localStorage before the user requests it • Minimize delays in rendering UI components due to cascading changes with asynchronous execution Source: Miramar Naval Air Station, aka “Top Gun”
  16. 16. So how does React work? • React’s building blocks are Components • Components are JavaScript objects tasked with outputting HTML • Only requirement is a render() function that returns HTML • Components can maintain their own internal state
  17. 17. A dumb component <div class=“commentBox”> Hello, World! I am a CommentBox. </div> var CommentBox = React.createClass({ render: function() { return ( <div className="commentBox"> Hello, world! I am a CommentBox. </div> ); } }); React.createElement(CommentBox,{});
  18. 18. A slightly less dumb component <div class=“greeting”> Welcome, Homer </div> var Greeting = React.createClass({ render: function() { return ( <div className="greeting"> Welcome, { this.props.username } </div> ); } }); React.createElement( Greeting, { username: “Homer” } );
  19. 19. A slightly smart component var UserList = React.createComponent({ getInitialState: function() { return { users: [] }; }, users: function() { return _.map( this.state.users, function(user) { return ( <li className="user">{ user.name }</li> ); }, ) }, render: function() { return ( <ul className="users"> { this.users() } </ul> ); } # with no users (at initialization) <ul class=“users”></ul> # with one user (state changed) <ul class=“users”> <li class=“user”>Geoff</li> </ul> # with two more users and one removed <ul class=“users”> <li class=“user”>James</li> <li class=“user”>Su</li> </ul>
  20. 20. Smarter is not better • Props are immutable, easier to track • Favor props over state whenever possible • Make component functions as dead-simple as you can • Dumber components are easier to test, and likely faster to render
  21. 21. Components nest • Any complicated element or repeated set of elements should be its own component • When the parent re-renders, React figures out whether or not the children should remain, be updated, or be removed • Components can be passed in as props to a component or returned from a function in a component • React can render an array of components
  22. 22. React lifecycle • React offers a number of “hooks” that allow you to trigger events at certain points in the Component’s lifecycle • Examples of lifecycle events: when a component renders, when it gets updated state, when it is removed from the DOM • Uses: start a timer, listen for UI events, tie in jQuery or other libraries after a component is rendered, then remove those timers/listeners when the component is unmounted • Cortex uses lifecycle to trigger chart drawing with d3 and updates every 30 seconds
  23. 23. Use functions liberally • Functions are fast (mostly) • Keep logic in functions outside of render(). render() should look as much like HTML as possible. • Just like your Ruby code, many short methods with limited arguments makes for cleaner, easier to test code than one massive God method that does all the decision-making Source: Arkansas
  24. 24. Shared behavior • React components share behavior through Mixins • Mixins don’t provide the same inheritance or composition capabilities as Ruby (no overriding methods or implementations) • Example of shared behavior: all cards that collapse or expand have the same collapse/expand mixin
  25. 25. Lots of components! Page -> Dashboard -> Navigation -> Navigation Item(s) Card Collection -> FlashMessage(s) Card(s) -> Card Header Card Chart Card Tab
  26. 26. Lots of components! Let’s take a look at the components in Cortex
  27. 27. React tips • Don’t manipulate HTML yourself! React can’t keep track of HTML changes you make after rendering. If you’re tempted to use jQuery or another library to alter HTML, figure out a way to do it through the component’s props and state. • Don’t be afraid to break components into smaller sub-components
  28. 28. More React tips • Components can communicate with their parents through functions. Pass a function from the parent to the child as a prop, then the child can call it and send a message to the parent. Super useful, but don’t overdo it! • Start small. One of the best things about React is that you can implement it in little pieces in your UI as you find opportunities to use it.
  29. 29. What about global state? • In our first attempt at using React, we had a top-level “Page” component that rendered all the various views inside of itself. The Page was responsible for maintaining global state such as the date being viewed, the current building, and the desired page. • Components would pass the global state as properties to children who often did nothing but just pass that state on again to their own children • It felt messy. It was!
  30. 30. Enter Flux • Flux is Facebook’s answer to storing global state in React apps • Flux data is kept in “stores”, which announce changes to React components, which can update stores with “actions” • A dispatcher ensures that updates that depend on other updates don’t get deadlocked
  31. 31. Flux Architecture Source: Facebook
  32. 32. What did we lose? Here’s how the application has gotten worse: • Application is considerably more complicated than when it was just Rails and jQuery (this would have happened with any of the other JS frameworks) • More places things can break in our code • React is much harder to test well than Rails with Capybara • Some co-mingling of business logic and our presentation layer
  33. 33. What did we accomplish? Here’s how the application has improved: • Application is much faster from the user’s perspective • Feels more “native”, with no reloads and quick changes after clicks • App is useful when the network isn't available • Ruby is responsible for our server-side work, and JavaScript owns the browser and presentation layer
  34. 34. Further reading • React.js: https://facebook.github.io/react/ • Flux: https://facebook.github.io/flux/ • Marty.js (a great Flux implementation): http://martyjs.org/ • React-rails gem (mount React components in views, compile JSX in asset pipeline): https://github.com/reactjs/react-rails
  35. 35. Questions? I’m happy to answer questions about: • React and Flux • Ruby or Rails • Cortex • Working as a developer • The awful state of the Boston Red Sox’ starting rotation
  36. 36. Thanks! Feel free to get in touch! twitter: @geoffharcourt github: geoffharcourt email: geoff@fivetool.io

×