 All right let's get this thing started. How the heck is everyone? I need more than that. Come on. How the heck is everybody? Thank you. Thank you. It makes me feel more comfortable. Thank you so much for coming to this humble little talk. I'm really glad that of all the talks out there you decided to come to this one. I'm feeling the feels right now. So in this talk we're gonna talk about JavaScript. I feel like I won a lottery being able to talk about JavaScript at a Ruby conference and I feel like it's one of those pieces of the real sack that's still just pretty terrible in general. And we have an opportunity to talk about how to make it a little bit better. But it's interesting at this particular conference there's actually been a lot of talk about JavaScript. I'm talking about like proper backpacks and like the zombie apocalypse and whether or not JavaScript should be in your zombie apocalypse proper backpack. Try to say that five times fast. And so I wanted to tell you just about how we solve the JavaScript problem or not how we solved it but how we're using the right view framework to help us write better Rails apps and better JavaScript on those Rails apps. My name is Michael Chan. Go by Chan Tastic on Twitter and there's a much younger happy version of me you might find there. So I work on an application called services. It was launched in 2006 and started on Rails 1.13. Services is an application for churches actually. It helps us help churches organize volunteers. There are timelines, services, all that kind of stuff. It's pretty cool and believe it or not there is actually a market for church software. So I mean it started in 2006 so our approach to JavaScript has kind of been yes, write it. And as you know after a little bit of time Sprinkles tend to turn into mountains. So we needed a way to better structure our JavaScript applications, right? So in 2012 when we were writing our second app we started to kind of look at the landscape and see what people were doing. So we looked at bigger Rails shops. We looked at Shopify and they were just starting to work on a project called BatmanJS. Has anyone in here used BatmanJS? Oh good for you guys or good for you all. Yeah so anyway so we did this and it was really interesting. I mean it had all of the kind of markers of a 2012 JavaScript framework. It was two-way binding and you set up a whole bunch of observers to kind of track state and update things and whatnot. And so we built our application in two pieces. We had the API on one side and we had the client side app that customers actually interfaced with. Now this actually created a whole new host of problems for us, right? Because now we had two sets of controllers and two sets of models and two sets of validations and two routers. And like you don't realize how much you really enjoy form 4 until you don't have it anymore and it's like it's terrible. So really our app started to feel like this, right? We just had like two cakes like stacked on top of each other and like this was a terrible situation. Any change you know in the front-end app result didn't change in the back-end app and it's just no good. We sort of changed this app but I asked the product manager for that team I said okay do you have any particularly juicy cards where state was like just unbearable in our Batman app and was kind of solved in our when we moved it back to just rails. He said are you kidding like all of them? He then proceeded to send you like eight cards and eventually gave up and said okay just search for cards that have hard refresh in them. And so what this means is we had so we had parts of our app that were so unreliable that the best solution for our JavaScript application was just to say like oh if a user ever comes to this route it's probably not going to work let's just refresh it. That's ridiculous. So as you can imagine or as you might know Shopify kind of abandoned Batman.js in 2014 we're kind of like left holding his hand like what do we do like and they've actually been pretty vocal against client-side MVC since then. So this is Toby the CEO there just talking about how ridiculous client-side is. I think he tweeted at some point about how the Batman project could cost them like a hundred thousand dollars or something like that just up in smoke. And as David mentioned yesterday or on Tuesday Batman Shopify has been really instrumental in kind of building out TurboLinks 3. So again we kind of followed Shopify's lead and as we built the rest of our apps or rebuilt some of our Batman apps we rebuilt them squarely on the rails path right and you know rails path sprinkles sjr turbo links and actually to be honest we kind of like it I know that's you know like controversial in here but like you know we're pretty into it. But we were still writing a lot of JavaScript there were a lot of places this is from pull request that was opened it's just a gift kind of like showing something where we have a lot of like transient state right like this isn't event that's this isn't an event that's going to get sent to the server and then respond with some you know server rendered JavaScript right like this is purely for the user this is just a user interaction it doesn't need to be handled by a rails controller. We also have pages that are like fully real-time so as I was saying we have services we have a service that plan helps you plan services and then this is kind of like a rundown for that and this happens in real time you have we use pusher to connect a ton of devices we have iOS devices and the person running the presentation can you know move through and that's gonna kind of change these items attracts how much time has gone by there's like a real-time chat thing it's like I mean it's pretty exciting it's like a JavaScript NBC's person's like a dream. So what we needed was we needed something that would actually scale from these small interactions that we needed it for to these big full-on pages of our applications where everything was real-time we found React to be instrumental in that and instrumental in us being able to stay on the rails path but then just use as little JavaScript as we needed to solve a job particularly this concept of react components so we'll talk about that a little bit more I have two goals for this talk so my first goal is that you'd be able to walk out of here and ship a react feature in an hour take you like five minutes to set up and then like you have 55 minutes to code so that's my goal if any of you accomplish it tell me and I'll like give you like a digital high-five and then my second goal is that you don't make the same mistakes that we did we made a ton of mistakes I mean as you can see we made a ton of mistakes in JavaScript and we made a ton of mistakes just porting our application logic to react so I don't want you to make the same mistakes that we did I'm gonna try to show you kind of the ideal path that we're using right now for all of our new development so let's do a react primer react is a JavaScript library by Facebook it's for creating user interfaces using components components do three things they render they receive props and they maintain state you you do pretty well to think about a react component as a partial with locals so let's say we have an audio service and we want to show the songs that are in this album right so this partial should make sense to anyone who's done rails for a day and so that'll render out something like this it'll render out an unlawful list of songs this particular list is 1989 by Taylor Swift yes thank you I may or may not have been able to create this list from my mind but so we're just gonna do the easiest steps we can right we're just gonna create a new partial file we'll just dump the whole thing in there and then we'll say render songs right easy so now if we really want this to be reusable right we can't say album songs here right we want to kind of abstract that a little bit and so we'll just say songs will require some type of local data and then our view we update this to say okay songs is gonna be album songs and so now if we want to show a list of Taylor Swift albums these are like I each of these albums has to have like at least 50 plays on my it seems like she's the best so we're just gonna iterate over the albums I'm gonna spit out a title and we're gonna use our partial again now these are different but because we're yet because we're sending songs in as locals it doesn't matter the partial doesn't care so you know this so let's do it in JavaScript now so instead of render partial we have a little helper called react component and instead of using songs which is going to look for the songs partial we would use the songs which is going to look for the songs component the window object yeah which one oh sorry yeah yeah so I'm gonna sorry this is the same partial code I'm just blocking parts of it out so all right so now we're gonna grab songs off of the wow these are terrible now thank you thank you for that so we use the songs component off the window object I mean instead of sending locals in we just send a hash in but it's the same thing we just say songs album songs and in react we call these props short for properties so props are immutable kind of if you were at you who does rust talk yesterday he talked about how rust has this concept of ownership and borrowing and how ownership is the right to destroy or modify something and when you pass something down as props like that component should not modify it destroy it like they just have the ability to view and use it so let's define our component is it can everyone see this now everything's looking good okay cool we have we have a songs variable say react create class it's a class with a render function okay we're gonna render out a on our list we're gonna grab the songs off of props and I'm gonna iterate over it with map so it's a little bit different than the ruby code above it and because we're gonna have blocks we're gonna actually call function for each of these for each of these items which is gonna take the song and spit it out as a list item song dot name all right let's go let's go over that one more time again just real quick so if songs it's react class has render function ul grab the songs off of props maps over them calls this function for each song and returns a list item with song name okay so let's practice so I had this idea of let's take a rails app that everyone here knows about we'll take the 15 minute blog and we'll add some real-time comments to it whoa okay so if you haven't seen the 15 minute blog this is the inverted version of the 15 minute log so there's a there's a block in there like this where we have posts we're gonna iterate over each comment and spit out the comment body with an HR because it's 2003 so let's go straight to straight to react so we'll create a comment it's react class the render function and that render function is going to return a deal with an HR in it and we're going to take our comment right off props and interpolate that out okay pretty simple so here in our view we're gonna use our react component helper we're gonna spit out the comment component and it's hard to say I should have chose a different example comment component and use the comment up body there right so our app goes from looking like this to looking like this the astute viewer will say those look exactly the same and they would be correct except now these two comments are being rendered in JavaScript so that's pretty cool so let's let's do the rest of this we're gonna take the whole block now we saw this with songs gonna create comments it's a react class the render function spits out a div takes all the comments maps over them runs this function for each we're gonna pull out the body of the comment and in react we have this cool syntax where we can use our comment like like an HTML tag right so we didn't have to do anything we just run that and we can send in a comment like we were with props as an HTML attribute so that's cool so we're just gonna send in the body cool take that out change this comment send all the comments down and now our app goes from looking like this looking like this the astute observers again say that looks exactly the same and you are correct except now the entire comment blocks block is rendered in JavaScript it's pretty cool so let's get to the real-time bit right so we have a comments component that renders out comments we have a comment component that renders out a single comment we're gonna create a comments container and what this is you can think about this kind of like a Rails controller right so this comments container it knows how to fetch comments and it knows which component to render when it has the comments it wants so again think about this kind of like a Rails controller this isn't special it's just kind of a convention this container convention so here we're gonna kind of ditch all the stuff that we had before we're rendering out the comments directly and we're going to now give so we're gonna use the content comments container and we're gonna give it a path now and say hey this is where you're gonna fetch comments this is where you're gonna fetch the JSON for comments this is that what that comments container looks like this first half is the fetching of comments we have our render function at the bottom and we have this get initial state so these are the API's that we're gonna talk about this is these are just the things that we haven't talked about yet these are for kind of managing state and whatnot these are the place where we actually interact with and set that state so let's let's dive into it so we have a comments container it returns a comments component and we're gonna start by just giving out comments of like an empty array right so this isn't so this is gonna render out nothing hey this is our first interact interaction with state as we have a special object for that and react and there's props and state it's the only two ways that you interact with data this is the second of those this is state so where props is immutable state is designed to change this container this comments container knows what state comments is in and it knows how to get new comments and how to set those comments so now we can use this this API called get initial state and this is just a way to kind of protect ourselves and when we're doing an asynchronous call to the first time we render render with an empty state at least not send undefined all over the place so again our we're getting our state from comment state all right so this is our function this is pretty simple we're actually I'm gonna take the comments path prop that we sent in and we're gonna fetch that JSON on six oh sorry that we passed in from that view on success we're gonna take that data and we're gonna use a special function called set state I'm gonna say hey the state is now is now the new data that we got back you can think about this set state as like a refresh a refresh button for your component okay it anytime you call this method with new state it's going to totally re-render anything that's down line of that tree so in that case it's going to render our components or our comments component and subsequently every component after that we have another hook here that we can use it's called component will mount and that's just an initializer function so when this components ready to go it's initialized we can run this function and here we're just gonna say hey get get all the comments and we want to do that every second so we're just gonna use polling for now I'll show you some more interesting examples later so now for the first time we actually see a change hopefully you can see it but as I add comments to the left screen they're gonna get loaded in the right screen this isn't particularly exciting but we didn't write a whole lot of code to get here and the code that we wrote is all in one place like it's totally isolated to those three component files we didn't have to change like you know a JavaScript file and then update our view to have like a dom node and all that kind of stuff we just it's all there this is totally isolated we can you know implement it totally differently you know in the future if we need it it's very cool so another cool thing about react I want to show you is it's very smart about the way that it does updates might be kind of hard to see but if you look at that list of comments you'll see that it's only doing an insert of the last comment that I added so the way this works is that react does re-render on on every set state so right here we're setting state with new comments it does re-render but it renders in memory and it just does a diff to say like hey how am I different than the dom and then it renders or it says okay we need to change these few things and then we'll be up to date but it doesn't like grab the whole thing out and then just do an insert of the whole common block this is also pretty cool for a lot of performance reasons so I showed you about like four things right there to actually manipulate states so what are a lot of we're the number of things that you need to know to be effective with react right off the bat well it's not too many I'll show you a couple of things that I've shown you already and those that we haven't so so first this is how you render out a component in your jobs group or in your Rails views this is how you send in props super easy so this is a greeting component we're gonna say hi Bob or something like that this is how you define a component we're just returning an h2 that says hi and we're interpolating the name out and there's a thing called prop types which is pretty cool where you can actually specify what type name should be which is really handy when you want to read for the for the reusability of these components it's really awesome because now in development if someone tries to use this greeting component and they're not quite sure how it works if they try to send in a number they're gonna get a really cool error like that or warning like this in the console and it's just gonna say hey you're trying to use greeting but you're sending in a number as name and we really need a string there's a method called get default props and this is kind of like set initial state or get initial state where you we can set initial value so if someone uses this component and they don't pass in a name we're just gonna say guess so we'll say hi guest and kind of think of this as like already equals in Ruby set state this is like the refresh button of your react components again initial state you saw this we can kind of set an initial state for our component component will amount this is where you would do things like get JSON this is as soon as the components ready we're gonna fire off something and you know get some new data and handle that data it also has a sibling called component will unmount and this is for things like if you are attaching event listeners so you would have component will amount component will unmount as this component goes in and out of you you'd attach a vent listener and then you would kind of remove that event listener clean up after yourself this works if you were using service and events with pusher we're using pusher pretty cool so it's about nine things you need to know like that's not a lot of things right a lot of things you guys live out there you gals alive out there everybody live out there this is nine things this is incredibly small amount of things that you need to know and we're not telling we're not telling it how to be smart about updates it's just doing that by itself we're not you're not grabbing dominoes and like changing them out and doing all this stuff we're saying hey we want this to render whatever the state is just like you know render that state you know just every time you render just you know do it the right way and then figure out on your own time how to you know insert in the most effective way so I want to show you a little example this is from our services live app that I was telling you about in the beginning so if you watch you can see the clock in the app looks so weird so you can see the clock and you can see on the right the only updates happening is is that like inner HTML which is really cool like I mean this whole like in memory this entire app is re-rendering and it's just sending in the it's just sending in the new time so this is we're getting you know second snapshots of this application here's the the chat application as I had comments you can look in the the table right there it's just going to insert those table roles rows so I want to talk shift a little bit to implementation so this is something we struggled with a lot there was at one point every single app that we had that used react was doing it a different way so I'm not going to tell you all five or six ways that we were doing it but I will tell you the way that we that we landed on the way that we feel is the most effective and the most honoring of rails in the asset pipeline so we use react rails gem this buys you a couple things it buys you that helper that I was telling you about the react component helper that we've been using in all these examples it's really smart it uses ujs to mount and unmount your components and it's really smart about turbo links so whether you use turbo links or don't use turbo links it's going to do the right thing it's very simple to set up you just add this gem you run this installer and installer is really pretty minimal all it does is really give you a components directory to you know to put all your components in it also gives us you this really cool generator so you just say react component greeting and I'll spit out this really cool you know all the code you need to render out a greeting it allows you it has a nice little syntax for prop types so if you know that you need a name and a string it'll render out this for you with the prop types in the top so if you haven't used rails assets this is incredibly cool project what it does is it works on bower and so it will here let's see it works on bower so in your gem file all you have to do is add this source block and then you add the you add these gems that you can find on the react rails assets site and so as you can see there's just a prefix that rails assets alts rails assets react router or whatever and what what rails assets does is it works on bower and it'll pull down the bower repository alt or react router or moment j s it'll pull that down and it will create an honest to goodness gem for you and return that to you so you have like a honest to goodness gem created from a bower JavaScript or CSS repository and this is super easy this is the easiest way that we found to be able to pull cool JavaScript libraries into our rails apps so the mistake we made was fighting the asset pipeline we worked a lot with trying to use browser fire webpack and all this kind of stuff and there are benefits there and I'd be happy to talk with you afterwards about what those are but we found that for the most part the easiest the easiest solution was the best solution for us so this is great it communicates well our teams are really happy with it let's talk about languages so some of you might have been watching and saying like okay I don't understand what this what this magic is happening the whole like HTML and JavaScript and so some of you might have heard the controversy around JSX and I don't really think this is a big big deal I like it I like seeing a JavaScript right here in my components it's nice that I don't have a separate file that's doing this at the end of the day it's no different than the way like ERB works or handlebars works it's just processing out it's preprocessing our JSX into function calls like this but we don't have to look at that we don't have to write that we just write it as if we were writing HTML all right so that's the JavaScript one react rails comes out of the box with support for coffee scripts so you just pen with coffee on the back so you lose a couple brackets and parentheses and whatnot the weird part is that you have to back tick escape out the JSX which isn't a huge problem if you really love coffee script that much we don't so we just don't use it it's also weird that you have to use this because this being back tech back tick escaped and you can't use at inside your component you can use it everywhere else but I'm sorry inside the template use it everywhere else but on inside the template so what we've really come to love is yes six there's a little flag you can set up in the react rails gem that will convert yes six into yes five for you so this is great now this has a little bit of a different syntax which is just fine you get used to it we really love it because it buys us all the things that we really love about coffee script but not copy script and we can just return this JSX right there so the first thing that's a little bit different is that you define things as a class so we define this as greeting class and it extends react components so before we were creating we were using create class to define our components here we're going to just extend the class react component also prop types get pulled out of of the class and they're used as a constructor property two things pretty simple one nice thing is that you can actually react is extremely smart I was telling you about the great warnings and errors that you can tie into so if you try to use an API that's strictly dedicated to the Kriac create class way of doing things when you try to do this as a class you're gonna get a warning and it's gonna say hey get initial state was defined on go comment a plain JavaScript class this is only supported for classes created using react create class did you mean to define a state property instead look this is an amazing error and it's like all just like switching from like JavaScript like ES6 and like look they're doing amazing like I don't even know how they like figure this out for me and they're telling me exactly what I need to do they're telling me where I need to solve this problem and what I'm doing wrong I need to do you can learn a thing or two about copywriting from this error this is amazing anyway so we go and oops we changed that to the right thing which I apparently don't have a slide for so early on we made the mistake of not embracing JSX we did a lot of somersaults to try to get around using JSX and just drawing out the functions ourselves and coffee script and whatnot and we found that the best path is just to embrace JSX you really start to love it after about like an hour and this is where Facebook and the react team is hiding a lot of the implementation details from you so the most painful updates that we've ever had are the ones where we were trying to use coffee script instead of JSX and something wasn't hidden from us because of that so use JSX it's awesome don't make the mistake we did use JSX is really great and I'm starting to see more and more documentation and react I'm using ESX I think it's the way way moving forward I a lot of people who are using react really embrace ESX so I want to leave you this morning with just this concept of only as much JavaScript as you need the idea here is stick to the Rails path as much as you can and just just do the minimal amount of JavaScript you need and I feel like react helps you there so this is our oh man my cakes look all funky now so this is your Rails app inverted this is your Rails app with sprinkles and this is your Rails app after two years of sprinkles this is your Rails app using a client-side NBC and this is what I imagined TurboLinks 3 to be like where you're actually using the sprinkles to kind of like pin down the Ruby views on top of the cake but I don't know and this is the party that we're having with react JS at Planning Center thanks so much