 So everyone's really excited. There's lots of space in the front of you would like to come up here to sit down. If you're standing at the back, there's space up here unless you wanna get your steps in. Cool. So welcome to our presentation. This is Masters of the Universe, live coding a React application using Drupal services. This is gonna be a live demo, so there may be some excitement and some thrills. We ask that you leave your questions, comments, and tips until the end. Unless I'm crying, in which please come and help. Or if you wanna help with the coding. Yeah, that's fine too. Just chime in. Cool. So, what we'll cover. This is just a large overview. We're gonna be talking about who the people up here are, what progressively decoupled is and how we use it. I'm gonna give a light touch on React licensing because I know it's a sensitive subject. And then we're gonna actually go through the build process in terms of how do we define kind of the data structure, how do we set up Drupal, and how do we set up React. If you're an expert at this, this will probably be old hat to you. But if you've never encountered this before, we're gonna give a really high level overview to understand how you can actually build these tools yourself. So the intention is that this isn't a deep dive, this isn't a complex discussion of something, but it's kind of like a cooking show. I'm not gonna like chop the carrots, but we'll show you how it's done. And if anything goes wrong, you do have the finished turkey at the end that we'll pull out. And that'll be the razzle-dazzle that we're looking for. I'm Justin Longbottom. I'm a Drupal developer with MyPlanet. We're based in Toronto. I've been doing Drupal development for about seven years, I guess. Lately, been kind of experimenting more with progressive decoupling, using React to do that, embedding that into our web pages to provide rich experiences. And yeah, those are my Twitter handle and d.o profile, so follow me, add me. Some of the repo that I'll be using later, it's not public right now, but the goals to eventually get to that point. So watch for me on Twitter and I'll tweet when that's ready to go. It's also his birthday. Oh yeah, it's his birthday. Yeah, it's quite the birthday present, so hopefully everything goes well. I'm Erin Marchak. I am a Drupal practice lead at MyPlanet. We're out of Toronto. And I focus on building out Drupal teams, mentoring users and embedding on the teams as a technical architect so I can work with people and learn and develop their skills. So the idea of learning and introducing new people to different things in Drupal is really important to me. You can, again, Twitter and d.o are up there. If you have any questions or are confused about any of the resources or anything, please follow up with us on there. We're always happy to chat. So what is progressively decoupled? We've heard a lot about it. It's been kind of kicking around the community for over two years, so it's kind of done, not done, but like, it's well used and well known. Established, thank you. And what it does is it allows us to embed decoupled applications on a standard Drupal page. So there's components of the page that are decoupled, that are rendered using client-side technology that allow us to kind of maintain the authoring experiences of classical CMS. If you work with users that are used to the Drupal UI and how that's kind of patterned in any kind of version control or work flowing, you still have that using a progressively decoupled approach because it's so closely tied into the classical CMS. If you use panels, you'll still be able to use panels because progressive decoupling doesn't necessarily exclude any of those standard technologies that we're used to. And you can use it to utilize the experiential benefits of the modern web. We're used to app-like interfaces, we're used to personalization, we're used to customization, and we're used to really snappy, sexy things on the internet. And so you can still provide that to your users without actually abandoning any of the SEO, archiving accessible or accessibility or any of the other benefits of the classical CMS. The other double benefit is create once, publish everywhere. So if you create a progressively decoupled experience, you're creating a backend that publishes an API, which we'll show you how to do. And that API can be consumed by your decoupled application. It can be consumed by a third party. You can pipe it into another interface, however you want to choose, but it allows others to actually access and participate in the API. When we do a decoupled or progressively decoupled site, we frequently reuse API endpoints between different areas of the site so we can pull in information and reuse content. And then we can also share that with third parties that want to either consume or syndicate our content. Additionally, with a progressively decoupled approach, you can personalize content really easily without pulling a third party integration lift. That it allows you to personalize on the client side, so you're still serving content through varnish, through cache, and through any CDN that you have. But the client experience is a personalization without the full kind of bootstrap cost of a session that would allow you to, or that would require you to bypass varnish. Finally, one of the benefits that we have is it allows really diverse development teams to work in parallel with one another. If you have a team that perhaps isn't used to Drupal but is very used to any kind of front-end framework, then you can actually start building in parallel with each other, having parallel sprints, and it means that as long as you're able to coordinate your efforts, I'm gonna show you how to do that, you can actually multithread your development processes, so which is a little ridiculous. The example that I have here is from a travel website that we do, and a lot of the progressively decoupled pieces that we work with are very similar to views, filters. It allows users to kind of interact as a catalog. It's a little bit faster than you would with a traditional whole round trip to the server interface. So this interface here, you could see, in a standard environment, I would build that with views. This goes across America and you can search different things here, but because it's decoupled, when I search, it actually changes the interface really, really quickly. Oh, come on. There we are. Okay, I had to start doing it. And you can see how the numbers start changing. The price I can change really quickly. I can search by Alaska. There's no more trips to Alaska right now. But it's really quite fast for the user. And so, when building these rich applications, you can cater to the user and you can give them that exciting experience that they're used to and that frequently, if you're doing any kind of high-end products or really cutting-edge stuff they're demanding, while still also leveraging the benefits of Drupal. Okay, so React licensing. Who here is aware of the React licensing? Raise your hand. Ooh, okay. So there's a few things out there. So React is released with a BSD license, so it is quote-unquote open source, but it does come with what's called an additional patent writer. And what Facebook has done is it adds an additional clause to the license. It means that out of the gate, this is not compatible with Drupal's license. So it's not really suitable if you're looking to use it for any kind of contributed work or any kind of work actually that you wanna host on Drupal.org. It's in violation of that license, so it cannot be hosted on Drupal.org. So it might not be suitable for a lot of different contributed projects that you're using. It's for sure not suitable in core, but it may be suitable for the work that you're doing individually with your projects if it's custom work. In general, I highly recommend asking a legal advisor if it's pertinent to you. Because it's a patent writer, it's specifically focusing on intellectual property rights and patents, and that's so contextual and so specific to the work that you're doing that you really need to understand what's happening and understand how to use it. So moral of the story, take it with a grain of salt. It's a really great tool to use, but we need to have an awareness of what kind of legal implications are there. Cool. Disclaimer done? Oh, no, no, it didn't work. Okay, so what are we building? A blue screen of death. That's just our lives now. Okay, cool, that's fine. No, no, no, let's get going. What are we building? So what we're actually gonna show to you today is a progressively decoupled Drupal application in which I will be programming the back end with a custom API endpoint and Justin will be programming the front end. Yay. And how we do this normally in production is when we start off our project, and we know that there's gonna be two teams in parallel that are building together, we define a common data structure, we define a language. You can do this with something as formal as JSON manifest. You can do this, you can commit the version of it, you can also scribble it on the back of a napkin, but in the end it's setting the team's expectations, so as the two teams work together to meet at a common goal, they're actually, they understand what they need to do and how they need to communicate. So what we're gonna do is we're going to create a little cover flow album interface, and Justin and I have chatted. I'm gonna send him the title of my album, the artist of my album is a string, the year it was released, and then a year all passed to the cover. So we just kind of define it there and we're gonna use the get method. And once we have that, then we can start working together to actually build it in. Cool. Sweet. So this is the fun part where the screen goes. I'm gonna actually set up Drupal for you. Boop, boop, boop. So we, so what we use to set up Drupal is actually, we've actually open sourced our scaffolding system. So if you go to pack.gis.org, my planet Skeletor, which is the reason why this thing is masters of the universe, is we have a small installation profile that extends what Drupal Composer does and we've customized it to our own use cases. So in here you can find some examples of how to properly set up and extend post install hooks with Composer and a few other tweaky tweaks. I have not trusted the wifi here, so I already installed it, which is fine. So I have my Drupal site. I have installed my planet Skeletor. It's pretty easy to install it. You just do Composer, create project, my planet Skeletor, and it'll bootstrap everything for you. I have already installed this site and I've made a little module in my modules folder. So I have it under doc root. I have it under modules. I made a little custom module called masters of the universe. Thank you. And within here I've installed a node. And here I have my album. I've installed it with some config. I have a body. I have the artist title as text. I have the cover image and I've field released. So what I'm going to do, at this point I have a handful of bits of content. Within here I need to log into the site. So I'm going to use my little script here. Drupal user login URL one to see the bit of content. So if you haven't encountered this before, this is Drupal console. It's sweet. It's really fast and it helps you scaffold tools, different tools. I'm going to be using one command mostly which is the generate rest resource to actually show you how to build your own rest resource. So we, logging in, I have my site. So the first step in towards building a backend is to obviously generate an endpoint for your front end to actually hit. And in Drupal 8, how we can do that and how we're going to be building it here is by using a custom rest resource. There's lots of different ways of doing it. We found that custom rest resources are more suitable to our needs, especially when dealing with large data sets. And I'll go over kind of the pros and cons of them. But step one, once I have my site, I have to install my module. Step one, install module. Module, Drupal. Module, install masters of the universe. Mm-hmm, mm-hmm, mm-hmm, mm-hmm, mm-hmm, mm-hmm, mm-hmm. Cool. And so it's installing my field UI. I have the rest that's out of core and some serialization. Everything that I'm using here is straight out of core. So it's really easy for you to extend and build out. Great. If you have it, I should now see content type. Nice. And I'm going to generate some content with it. Drupal, create nodes, just to kind of generate what's going to be in there so I have something to play with. Yeah, yeah, yeah, yeah, yeah, yeah, yeah, yeah. Great. So now I have some nodes. So let's actually generate the rest resource. Drupal, generate. Ah, ah, ah, ah, thank you as well. So I'm going to generate the rest resource. Yeah, that's better. And the awesome thing about Drupal Console is it actually walks you through it with type ins and auto-completion. So if you're not really sure about what's going on, you can step through it. On top of the fact, they have a learning flag, so when it does generate content, it'll generate more descriptive comments so you can actually go through and see and understand what's happening. I like it. So I'm going to give the plugin rest resource name. What did I decide? Al, bum, rest, resource. I'm going to call it albums. Sure, that's a human-readable name. My URL is going to be api-slash-al-bums. Yeah, and it's just going to be a get because we're just going to be fetching it to build out our little cover flow view. Yes, please, I like generated, oh, so fast. And you can see here in my module, whoop, I now have my album rest resource. Yay. The one thing that I found with generating this is that when you generate a rest resource, you have to enable it. There is still some configuration. There is an awesome module called rest underscore UI that you can use to kind of control and cookie pointy and like go through all of it, which is great for exploration. I'm ridiculous, so I'm using Drupal console to do it. Drupal rest enable. Oh no, I did this before. Rebuild caches. And then you can start enabling it. Mm-hmm, mm-hmm. Drew, Drupal rest enable. Albums, you can see my auto correct. I would like to enable it for my get method, which I've defined. And then I could actually control the format of the output of it, and it'll handle this auto-magically. I'm going to use JSON because it's going to be consumed by the front end. And I could provide authentication, which is cookies, select authentication providers, and it's already enabled. The one thing that I will notice or I will point out with this is that when enabling rest resources, they are tied to user permissions. So after you enable it, you have to go to permissions and access get on album rest resources. And that's really nice if you have multiple kind of levels of control, whether or not you want to have access, different users have access to different parts of the endpoint, whether or not you're creating or just reading content. Cool. Saving permissions. Sweet. So if I go here, I use Postman to help me test API endpoints. You can do all sorts of cool authentication and headers. Here's what in the end we're going to build right here. You can see it's the same match except this is a ridiculous artist's name and I don't know how to pronounce these hipster bands. But if I was to hit the endpoint right now, send please if I need to flush caches. Ooh, never mind, don't see that. Old habits. Okay, well that's building. What I'm going to do is actually, I'm going to cheat a little bit and I already have some commits on how to extend the rest resource class and I'll show you what's currently in there before I apply the content. So if I hit send, implement rest state get and if I open up, presentation mode is great until you want to read a word. But you can see here in my module, it generates a plugin rest resource right here as I declared. And you can see that it's already set up my namespace. This dock block actually defines your rest resource so it's really, really important to have it set up correctly and that it allows you to actually create different rest resources from there. I'm extending the rest resource space and I have some additional classes that kind of help me pull in. But the key part is that you have these suite methods for each individual method you can actually post to the rest resource or get or whatever. So here we have get and you can see here I'm doing a little permission check and I have access to these new classes that allow me to return it. So this one is a rest resource response, implement rest state get. So what I'm going to do is get stash. Get check out. Think I want stash in. And did this add it? No, it did not. Let's move on to the next step. One moment please. Cool. So here I've cheated. Instead of typing stuff out I've just checked out my next commit. But what I've done here is I've added actually the database as a service within my rest resource so I can start querying the database and building out my custom query. And because we're also sending files over if you remember, we committed to actually sending the full file path over here. I'll actually need the public stream wrapper class to generate the file path. And so I've set them the database query method. I've set that as a little variable. The file path I have a file dir here and I'll be able to kind of control it here. Then once you have all of your services built in and put in here, then you can actually start building out. So what I wanna do now is build out the full rest resource response which I have done in step eight. Boop, great. So all I've done here is extend out the get method. And what I'm doing is I'm looping it within a try catch block that if I fail to catch it I'm gonna throw a bad request HTTP exception. There are a lot of different ways to actually return an exception when handling a rest resource. And so you can really tailor it to whatever you need. In the end, it's gonna set the header properly for you and it's gonna provide a contextual method for your front end guide actually handle it. Here, if you've ever worked with database queries before in Drupal seven or eight, it's fairly standard. What I'm doing is I'm just connecting up the node field data with a handful of different fields with my joins. And then here for each added field or add expression I'm gonna add an additional parameter to my endpoint. So I have the title which I've mapped out, the artist which I've mapped out and you can see that I've included expressions. When dealing with large data sets or more complex calculations in which you kind of wanna optimize the query a bit more, having a direct database query is useful to actually tweak and test performance because you can add these expressions and do min max calculations. I can format dates properly just in line within the query or I can do just replacements of text. This won't always be the fastest way but if you do this directly by hand you're gonna have more control and you're gonna be able to tweak and actually optimize the output to whatever your data needs are. And this is definitely something that one can do. A lot of this example can be used with the JSON API, GraphQL but if you have really weird data, if it's denormalized, if you're doing interesting joins and if you wanna have something that really kind of can be tailored to your use cases I really really like just doing a database query myself and then kind of handling it. I'm also one of those people that like whenever they have a good dessert they like make the dessert at home so they can get it just right. So I'm just picky. The benefit here, if you wanna start kind of debugging everything that's going on is I can actually take the query. Do, do, do, query, execute. And this is the get string query. This will actually get a string representation of your query that you can drop into whatever database you're using. You can drop it into PHPStorm which I use. You can drop it directly into your console and then you can using MySQL's explain method you can actually step through and see where your complicated joins are and see where you're wasting time or space. So it's really, really useful to kind of get in the nitty gritty and kind of massage it. The final step here, I'm getting the albums. This returns an associative array of albums and what I'm doing here is I'm generating a REST resource. If you haven't used PHPStorm or any object-oriented notation, this kind of funny comment gives context to the object. So here I'm saying the var response is a REST resource and that allows me to get PHPStorm. Ooh, get my type hints. So I can actually see the different content that's in there and what I can use. The awesome thing about the REST resource, or sorry, resource response, excuse me, is that you can actually set caching and it's cached by default and you can set cache dependencies using Drupal 8's caching APIs. So it's kind of already built in there for you and you have a lot of control over how it's properly handled. So I can either return a response or I set before a bad HTTP exception and let's see if it worked. I have to flush caches. Shocking. Go, go, go. Aha. So let's see if I have an endpoint. Yay! Did it. Cool. Okay, so I have an endpoint, that's great. I have this now cool thing that a machine can consume and now I would like to have an app that hosts on it. So the easiest way to do that is actually to generate a page controller using Drupal, console, Drupal, generate controller and this is gonna be the page that hosts the app. If you want to embed your app in a block, in a theme function, in whatever you totally can but for the purposes of this example, we're just gonna drop it in a page. We found that there is a lot of benefits to actually placing decoupled React applications in blocks, in panels, in however you want it in paragraphs, whatever. So you can kind of sprinkle this idea of content personalization throughout the site. So I'm gonna create an action method on my controller. If you haven't seen this before, this is fairly standard Drupal console stuff. It is totally described online really clearly. I'm gonna create a little app. It's gonna be at slash albums. Nope, I don't need to generate any of these for the purposes but I do need to confirm generation. There we go. So you can see here, it's created a little routing file for me, Qt Petuti and I now have my album controller and at this point, if I flush caches, flush caches and go back to slash albums, I'll see nothing because I haven't created an app yet. So I need to talk to Justin. Oh, I will jump in. With a really awkward laptop swap. Yep, well he's doing that. Oh wait, we have a Shira GIF. So I have built my app. And with some questions, as you set up. So I kind of touched on these questions. Why not use the core REST module or the JSON API? And I really do think that there's great benefits in using them. You need to plug in with this? Sure. Is there my screen? Yeah, you should log in first. I really do think that there's strong benefits in using core REST in the JSON API but if you have really oddly structured data, if you have denormalized data or if you have very large data sets, there is a benefit into minimizing the actual weight of the endpoint and you can do that with a custom query that returns a custom structure. I used a database query. Why not use entity queries? They're cached. Again, if you have really complex or interesting or denormalized structure, such as commerce entities, different entities that you have to join together, there can be performance benefits of just you rolling your own query. Finally, about caching and pagination. The REST resource response class allows you to actually handle caching yourself and any queries that you choose to use, whether it's entity query or the database query that you can roll pagination yourself. So it allows you to kind of tailor and customize the content as you need. You ready? No, I'm done, I talked through the whole slideshow. Okay, so I basically am resuming where Erin left off. Just in case things blow up, I have that part working, but great job, Erin. So we have the JSON feed here. Just refresh to confirm that it's working. Okay, good. We have the album page, nothing on it right now. And we have a little scaffolding app here that I set up. That's the app that I'll probably make public in the near future. So basically what we want to do is, switch back to slideshow here. There we go, there we go. So as we said before, it's progressively decoupled. So we're not, it's not running on another server, it's basically embedding in the page. So that's why I use the phrase embedding. We're gonna add it to the page that Erin created. So this is basically what we're gonna do. Quick prayer to the live demo gods. So hopefully things go smoothly. I'm going to, I'm actually not gonna clone React because I don't wanna rely on the wifi. I've seen some problems with that. So I basically have that kind of all set up ready to go. I'm gonna do an overview of sort of the scaffolding app that I'm gonna use. It's a Redux, React Redux app. Has anyone here worked with React or Redux? Maybe a quick show of hands. How many for Redux? Okay, so a few. So hopefully this will be interesting for you guys that I haven't seen that before. Redux is just a way of managing your application state. It's kind of our chosen way that we like to do things. It simplifies a lot of things. So I'm gonna go through sort of the architecture there, the justification for why things are organized the way they are. Redux is pretty opinionated, but there's some benefits you get from that. And then I'm gonna basically attach the app to the page. And we do that by creating a library. So I'm gonna switch back to the demo file. And then we'll maybe tweak the app a little bit, depending on how much time we have and see how far we can take it. I do have some branches at my disposal. If we run out of time, I can check those out and you can show you sort of a finished product or the cooked turkey using the cooking show metaphor. So I'm gonna switch back to PHPStorm here. I'm not a fan of presentation mode, but I'm gonna try it. All right here. So what I did is I took Aaron's app, basically, and I created a little JS folder. I cloned my scaffolding repo into it, renamed it, mastered the universe. And then we basically have a starting point. So what the scaffolding app is, is basically a simple react app. It fetches data from a remote endpoint and displays loops through it, assumes it's an array, loops through it and displays some properties. So sort of the use case where we'd use this is maybe a substitution for views. Like as Aaron said earlier, typically with views you change your search filters and it has to make a request to the server, make the full round trip back, update your results. That can be a slow process. Even a second or two can feel slow if you want a real snappy experience for your customers or whoever, for your site users. So what we're doing is basically loading all the data up front and doing the filter purely client-side. So we have all the data stored in the state of our application and then we can filter on it there, which means you can do the filtering very quickly, essentially. So I'm just gonna walk through the structure of the app first. So those of you who've done React would probably recognize some of this stuff. It's pretty standard. We have like a gulp file that grabs all your components, all your JavaScript files and merges them together and minifies them. That's what we'll essentially be adding to the page, to the library. The package JSON file, that's, you can almost think of it as your make file coming from Drupal speak, a list of your dependencies. And we'll show that real quick. So these are all the node packages that I'm gonna pull in to use. Some of them I probably don't need, but basically, yeah, it's all your dependencies. Now, this is kind of standard React stuff. The components, components in React are sort of, you can think of them as little snippets of markup, little widgets, little pieces. It can be something as simple as a div, a single div. It can be like a full, it could be a full application managing its own state and everything. In my case, I just have sort of a wrapping component called app and then the main component. So I'm gonna open up main component. And every component in React needs to have at least one method, which is the render, and that kind of returns your markup. Now markup in React is actually called JSX. It's like a pseudo HTML. It looks like HTML, but it's not. So you can add classes to it as you would in HTML. Of course, we have to use special words like class name. Class is a reserved word in JavaScript. So we kind of have a replacement for it here. So this is where I'm actually looping through the data and printing out all the different properties. So that's sort of the front end component of it. Now where it gets into more of the, I guess, redux land is these things called actions and reducers. An action is basically defining a way that you can modify your state. Any time the user interacts with it, they're sort of creating an action. So you wanna attach actions as callbacks on say a button click or a filter change or those sorts of things. And those are the ways that you modify your state. The reducers are sort of slices of your state. So in this case, I have a data reducer. So that's the data I'm gonna get from the endpoint. When the app first loads, there's a default state. So everything's basically, you can see null. I'm not fetching, it's not loaded. There's no errors. These properties are sort of flags that I'll use in my app. So when the Ajax request is in processing, when it's processing, I can set that to true and the component can render a loading message or something to that effect. Down here below, I have the function which is sort of essentially listening for these actions. So when you dispatch an action, say from a button click, it fires the action with this sort of a name. And then we can react to it here. What we're doing with a reducer is we're taking the state and we're modifying it. But one of the properties or principles of Redux is that you're not mutating the state. They're actually peer functions, which means you need to return a new state. And that's actually one of the benefits of Redux. The way it manages state allows you to sort of push onto the state stack. You can then get a history of state. You can have undo functions. You can record events. You can actually track every piece of interaction that the user does, which is really interesting for marketers too. It gives them a lot of analytic data. Take a drink real quick. You can see this one comment I put here. Something called object spread. So that's sort of new to ES7. Spread operator is pretty cool. What it does is sort of explodes out your object or your array, returning all the different properties. And then anything listed after it actually sort of overrides the existing one. So what we're essentially doing here is saying, okay, when we get our data back, we want our original state, but we want to update our data with the data we got back. And then we want to set these flags. So that's sort of the reducer. And the actions are where we actually define those things that can happen. So I have a few actions here. First one is get data. That's sort of a wrapper that we'll call the other actions, which I have listed below here. So the data can be fetching, we can get it back. You'll notice that this first one here is the only one that has an export, which means this is the only one we're gonna make available to the app. So the components gonna call get data. You can see I'm using Ajax, or jQuery Ajax here. Could have done it another way, but I think everyone's familiar with jQuery, so kept it simple. So it's actually gonna set our flag as pending. It's gonna fetch some data. I'm gonna have to update this to the URL that Aaron set up. And then when it's done, we're gonna pass the data, which is our response to the reducer, which will update the state. And one of the beauty things of React is that when the state changes, it'll actually re-render the component. So when we initially render the component, we don't have data, so we display a loading message. Soon as we get the data back, it will actually re-render it with it. So you don't have to manually tell the component to re-render. It'll just sort of happen. Some of this other stuff is sort of boilerplate, stuff for redux. The store is basically where all the state is managed. It's the single source of truth, as it were. With other architectures in React, you can kind of have the individual components managing their own state, which is called local state. That doesn't always scale very well. It can get really unruly. We've built applications without redux. And as you have different components, things build up, build up, and it gets a very complicated sharing state between components, getting them all to work together. It becomes difficult to track. So with redux, it has everything all in one spot, which makes it really nice for debugging. And there's some great Chrome extensions that are for React, and there's one for redux too, and I'll show a bit of more of those later. Yeah, I won't go any further into that. So let's actually update our URL here. So I'm gonna update our fetching URL. Oh, that's hard to see. Yeah, it's good. So I'm gonna just replace the dummy URL that I had there, and I'm going to update our response, because I believe there was a root of albums. So that's good. And then over here, that looks good. Let's do, yeah, sorry. Even bigger, all right. Even bigger. Just keep yelling at me tilts. Is that good? No. Oh wow, okay. How's that? I think so. No? What happened there? There we go. Okay, so that built. So now if I flip back to here, what it did is put our compiled file in here, or app.js, so that's what we're gonna attach to our page. How am I doing for that? 20 minutes. Okay, cool. So next thing we wanna do, now that we actually have a JavaScript file, we wanna attach it to the page. So I'm gonna create masters of the universe.libraries. Ding. Okay. And rather than make you watch me type that out, I'll just copy and paste that. I have a little snippet somewhere over here. My cheat sheet. So I'm basically just pasting in the definition of the library. And it's sensitive to the tabbing, so let me just correct that. Okay, so now we have a library. It's pointing to our app. And now we wanna actually add it to the page. So I have another one for that. So in the page controller that Aaron created, there's basically just a render array callback. And we just wanna attach it to that back to here. Let's see what we get. There we go. So it was pretty fast, but what's actually happening is the page loads, then the JavaScript executes, it hits Aaron's API that she set up, retrieves all the data, then we loop through it displaying all the titles. So at this point, we haven't really done anything that views can't do. It is pretty snappy, but what I wanna do next is actually add like search, searchability to it, so we can filter it really quickly. Before I do that, I'm just gonna show you some of the Chrome extensions we have. They're pretty neat. So there's the plain vanilla react one. It's kind of like the DOM inspector, but it just shows you the react stuff, so you can sort of see, here's what it's basically printing out, just bunch of divs. Oh, yeah, sorry. Ooh, can I zoom? Yeah, there we go. So available to our component, we have our data, which you can see here, and our action. So those are the two things that we've exposed. But now I'm going to add some search stuff to it. Cool. I'll update my URL again real quick, because I discarded my changes. Oh, and, go, watch, forgot about that. Golf basically monitors for file changes and will rebuild, so I don't have to keep flipping back here. Okay, so I'm just gonna show you the difference. So what I did is, I created a little on that commit. I created an input on key up. It calls the search title function, which is right here. And all that's doing is calling our action, which is a search title action. So I flip over to our action creators. I created a new one here. It's exported. It just defines it, so it's called the search title action, and it returns just the search term. And the search term is just the value that the user typed in. So they type, dispatches the action, passes it to the reducer. The reducer then does some filtering. Take a look here. So here's my search function right here. So I just wrote like a little one line searcher. So kind of a neat little thing I learned. Index of, if you use this operator, we'll sort of turn it into a truthy value. So, index of usually returns a character position, but this returns it to a true or false. So what we're actually doing is looping through our data. I've added a new property to our state called filtered data. So we now have all our data and then the subset, which is the filtered data. And it's filtering based on this little function here. We then update our state, update the filtered data. So we never wanna override the original data because that's sort of our whole repository of information. The filtered data is what we're always operating with. And then if I flip back to my main component, I'm now looping through the filtered data as opposed to the main data. And if I flip back to my app, we'll see if it works. There we go. So now, if I type, it should actually filter as I type without any Ajax request. So it's completely client side. See how it works. There we go. So it's pretty simple use case, but it's pretty snappy, it's really neat. So typically in this kind of architecture, what we're actually filtering is, in the example Aaron showed you was a vacation site. So they're not dealing with 25 albums, they're actually dealing with thousands of permutations of different destinations and different vacations. So we find it actually really useful to be able to filter quickly. It's a nice experience for the user to kind of not wait for that round trip back and forth to the server. See we're running short on time, so maybe I'll just check out the finished version. So what I did here is actually have like a little cover flow component. So coming from like a Drupal background, Drupal developer by trade, I always kind of find it interesting searching the d.o for a module. There's a module for that. NPM's pretty similar, it's always fun looking for something. So I actually just Googled react cover flow and sure enough, there's a component for it. So if I flip back to my thing here in my main component. So what I've done here is I've just wrapped, sorry, when I looped through my filtered data, I'm actually just printing out the images inside of the titles and then I'm wrapping it in this cover flow component. And that basically does all the heavy lifting. I haven't written any CSS. I've just basically made this little change that you see right here. So it's purely a front end thing. And I'll rebuild my app. We'll see if that works. Guess I did that already. Try and refresh that again. Oh, zoom out. There we go. And if I update it, let it re-render a bit. Oh, so I filtered it down to one. There we go. And I can scroll through it. And one last thing I'll show you. So there's, in addition to the React DevTools, there's the Redux DevTools. And basically that gives you some Redux specific tooling which is really nice. It can show you your history. So you can actually see everything that I did. I can go backwards and forwards in time. So I could actually skip back to when the app was initializing. I can click jump. And look, the whole app went back to the initial state. And I can go back to search here. And there's the state again. So it's actually really useful for debugging the Redux toolbar. I don't even really use the React one. It also has a diff. So you can see the diff between your state changes. You can record the state changes, export them, whatever. We often just push the entire state to some marketing data layer of some kind. So they find that very valuable. So you can get really fine grained reporting on what users are doing, which is really useful. Yeah, I'll wrap it up on that. We got what, a couple minutes. There we go. Yay! So we have a couple minutes. I don't know if we wanna open it up to questions. We could maybe skim over these. Yeah, if there are any specific questions that you wanna come up, ask them. I got a question. What would it take to get React to render on the server so that it's not purely client, so it's like actually working on it? React can be rendered server-side. I mean in Drupal, sorry. In Drupal. I actually haven't done that. That's an interesting idea. I know it can be done. In this sense, we're, yeah, I haven't really done it, but I know it can be done. I would have to imagine, and maybe somebody with more DevOps experience with node environments could jump into Azure this, but it would have to be part of your build process or any kind of cron job. Cool, thanks. How's it going? Good. Good question about the site that you actually built with React and Drupal, so. The travel site that we showed earlier. Yeah, the travel site. Yeah, so with Redux, you get all your data on the client, and I was wondering with like thousands of nodes coming through, how do you, do you get everything at one time or maybe everything 50 at a time and then like when you need to get the next 50, do you remember? We do paginate it, so what you could do is have the app render after you get the first page if you want and have the results filtering in. We tend to wait for all the results to come in before we show customers, especially when it's pricing sensitive, but yeah, we do paginate for large data sets. And optimizing the end points, so you can have a really lean data set we found is important, so we only tend to send information over that we need on the front end so you don't bloat it, so you can send more results. Yeah, that's kind of why we don't always use JSON API because it sends you everything and it gives you the full field name and you don't really need the UID or the published date for some of those nodes. So we keep it lean and keep the payload small, cache it, and it's actually, even with thousands and thousands, it's still a pretty snappy experience. Nice, thanks. Cool. In Toronto we have, we have a couple of offices and most people don't. And we've worked with a handful of universities.