
Alan Dipert | Integrating React.js and Shiny | RStudio (2019)
React.js is a thriving JavaScript library that eases encapsulating and sharing sophisticated component libraries. The React.js ecosystem is filled with components for doing everything from color selection (react-color) to animation (react-spring). While it's always been technically possible to integrate React.js components with Shiny applications, it hasn't always been particularly obvious how. To make it easier, we augmented the excellent reactR package with functions specifically designed to make it easier to create new htmlwidgets, inputs, and outputs based on React.js components. In this talk, I will further motivate and demonstrate these new tools and do my best to empower the audience to try them out. About the Author Alan Dipert Alan is a software engineer on the Shiny team at RStudio. In the past, he’s helped build web applications, reporting pipelines, and many things between. When he’s not working, Alan likes to spend his time reading or being with his family
image: thumbnail.jpg
Transcript#
This transcript was generated automatically and may contain errors.
Hi, everybody. Thank you so much for coming. I really, really appreciate it. I've been doing some very exciting work, and I'm really even more excited to share it with you all today. So I'm Alan Dipert. I work at RStudio. Like Barrett, I'm on the Shiny team. And I've had the pleasure over the past few months of working on this problem of integrating React, the JavaScript library, with Shiny. I believe that for quite some time, people in the Shiny community have been interested in React and about ways to integrate with Shiny, and so this work was initiated in an effort to bridge that gap somehow. And we've been at it for a few months, and we have work to show, which is why I'm here and why I'm so excited.
But some questions and problems remain unsolved, and that's sort of where you come in. So I would encourage you, if you're at all interested in any of this, to follow up with me afterwards. There may or may not be time for questions, but I'm always happy to talk about this stuff, and we can talk shop and discuss why you're interested in the context that you're interested in, because I think that this could be the start of a really fun and exciting little niche thing in the Shiny ecosystem.
Motivating demo: Mapbox GL and tacos
So without further ado, let's start with a motivating problem, I guess. A problem slash demo. So like many of you, I'm online, I'm on the web, I surf the web, and you come across things that are awesome, and the only problem with them is that they don't have an HTML widget or they're otherwise not accessible from R. So one of these things that I ran across was a React-based library called Mapbox GL. Mapbox is a company, they make a library called Mapbox GL, which is very similar to Leaflet, but it has some interesting properties. In particular, it's highly themable. So let me show you some of the demos of this thing.
So this is a very nice Leaflet-esque map, but of course we can do heat maps, pretty fancy, and you can switch between these. The thing that's governing the colors of the roads and the city and county titles and stuff, that's all governed by one of these Mapbox style objects, and then on the left-hand side here we've got the heap of JavaScript code involved in rendering that. Probably my most favorite one is the Superman mode one, where you literally fly around. Right? So just to be clear, I didn't make this, but I think it's awesome, and this is the kind of thing that I think gets me excited when I'm able to use it from R.
So what I did is I, in the course of not too long, maybe an hour or two, using the tools I'm about to explain to you, I was able to make my own HTML widget that provides a subset of the functionality we just saw and delivers it to us as an R HTML widget, and so I became aware early in the conference that the most important thing to keep in mind about here in Austin are tacos. So there's this, it's trending, has been trending, someone named Caitlin Houdon, I hope I got that right, who I haven't met apparently, posted on Twitter a list of her five favorite places, and then in our studio person Thomas Mock, he made a shiny dashboard using a leaflet map, and I thought, hey, in keeping with the tradition of taco enthusiasm, I should make some kind of taco app.
So here we are. I've got some taco joints loaded up into a data frame, and I'm displaying them with a data table here, and then over here I've got taco locations with fork and knife sort of blurry little icons, and then probably the neatest but also most awkward thing I can do is I can filter this, and after a little bit of burping, it comes back and you can see that we've filtered what shows up on the map. So like I said, this is like an hour or two of work. Now, granted, I'm like the world's expert on this weird little library, so take that with a grain of salt, but like I said, I'm always happy to help you use it.
So this is the promise. This is the kind of thing that I think we can do more of if we develop these tools that help us bridge the JavaScript ecosystem, particularly the React ecosystem, with Shiny.
So this is the promise. This is the kind of thing that I think we can do more of if we develop these tools that help us bridge the JavaScript ecosystem, particularly the React ecosystem, with Shiny.
The JavaScript code involved
So this is the all of the JavaScript code that I needed to write in order to make go what I just showed you. If you know JavaScript and are familiar with React, you might have a slight grin or even a smile on your face. If you don't know JavaScript or don't know React, you might be a little worried at this point, but don't be. I can assure you that the things you see here can be learned fairly quickly, and a big part of what we hope to do with this initiative is to build out not just the code to do that bridging that I mentioned, but also to build out the documentation and the recommendations around learning JavaScript, leveraging its ecosystem, and all those things that surround JavaScript development to make them more accessible to people who don't have that experience.
So this is the extent of the code that does the adapting of the React library I just showed to Shiny world, and, yeah, I think it's like 11 lines of code. I don't know. Is anyone surprised at how small this is or disgusted by how big it is? Show of hands.
So if you're the kind of person who would prefer to ignore me for the next 15 minutes and just start hacking, here are the URLs you need to know about. We have a GitHub organization, React-R, and that's what we call it because React without the dash R was taken, but if you go there, that's the organization. There are some example repos, and then there's the React-R package repo itself, and there's also a link to various other pieces of tutorial documentation. At the bottom, that will take you directly to our tutorial, which as of right now is the best way to ramp up on this topic, particularly if you have a little bit of JavaScript background, but if you don't have that JavaScript background, the rest of the talk is for you.
What is React?
So we're going to talk about what React is, why it's interesting. We're going to discuss the core unit of composition in React, the component, and how it's relevant to us. I'm going to introduce you further to this React-R package, and then I'm going to describe at a high level the process I went through to make that widget, and then I'll talk a little bit about what we have in store for the future.
So what is React? Well, it's a JavaScript library for making user interfaces. It was invented at Facebook around 2011. I believe they used it for the news feed, and then they bought Instagram, and I think Instagram developed it further, and after Instagram had refined the idea, they did a wide open source release. So it's quite a mature, even though it wasn't open source until 2013, it's still quite a mature library and has been used thoroughly.
It supports a functional approach. I think if you know how to write R, you already know what the functional paradigm is, so I won't elaborate on that, but that's another thing like React that's trending in the JavaScript ecosystem, but like I said, if you know R, you're sort of already on board, so I wouldn't worry too much about that paradigm or that word, and it's oriented around components. I mentioned that the unit of composition in a React-based application is a component, and finally, they invented a syntax called JSX that you can think of as a hybrid JavaScript and HTML syntax, and it really does make writing these kinds of applications quite a bit more concise, and we'll see some of that in a second.
So I think you should care about this for one of two reasons. One, you did like what I just demonstrated. You're on the Internet, you saw something really cool, you found it, and nobody's made the HTML widget yet, so you want to be the person to do it. That's a reason to be interested in React. It has a huge ecosystem with tons of things that deserve to have their own R wrappers, and I see if everyone in this class learns how to do this, maybe we could get a significant percentage of the React ecosystem into R. The other reason might be you're coming from a JavaScript development background, you have experience with React, and you want to build a React-based library, and maybe adding it to R isn't like an afterthought for you or would be icing on top, so that's another reason to be interested in React if you want to go deep on JavaScript.
I should mention also that the reason to go deep on JavaScript with React in particular is this just wildly, wildly, wildly popular and well-supported by documentation and communities and so on.
React components
So React components. What are they? Very similar to HTML tags. Honestly, they are I think of them as containers. They contain data hierarchically, so it's sort of a way to describe a tree. The big difference is that the HTML tags or elements are defined by a standard, the HTML5 standard is the most recent one, and there's a closed set of tags and closed set of behaviours for those tags. React components are different because you can define your own tags or components with their own behaviours that are specific to your library or application. They contain something called props. You'll see this term in React documentation. Props are basically a mapping or a named list of keys to values, and then they can also contain other components, again, because they're hierarchical, and applications are formed by composing these into a tree of some kind. And then once you finish composing your components, it's React's responsibility to take this user interface that you've described using React components and to display it efficiently in the browser.
So this is sort of the minimum viable hello world of React adapted from the Wikipedia page on React. There are four distinct code chunks. These wouldn't necessarily all appear in the same file. They could, but they don't have to. The first piece we're looking at here is the component definition, so a component is a JavaScript class, and here I'm using newish JavaScript syntax and classes in ES6, and so that's what we're looking at here. It is JavaScript, and we can see we're naming a component called greeter, and then we can see that this component extends something else called React.component, and what we're doing here is establishing a hierarchical relationship. We're saying this new class greeter should inherit all the behaviour of the super class or parent class React.component.
There's only one required method, the render method, and that method needs to return something, and in this case, this looks like a syntax error, but it's not. We're in JSX, that special markup I mentioned, so we're in a world where there's a hybrid JavaScript XML syntax at play, so what this is doing is effectively returning an instance of the H1 component which is built into React, and then finally we're interpolating a value into that JSX expression, so if you've worked with glue or other languages that support string interpolation, that's what we're looking at. We're slicing data from one context into a template, and this kind of templating is another reason that JSX is so handy.
Here's some more JSX where we're creating an instance of the greeter class. You can see the less than sign says we're creating a tag, and greeting is equal to hello world. This is the place where we assign those props I mentioned, that key value pairs associated with an instance of an element, and then finally we render the whole thing to the DOM, and the net effect, like if you were to right click in your browser or look at the elements in the inspector, you would see there's a div called my app with an H1 hello world.
The reactR package
So that's React in a very small nutshell. React R is a package that has been around since 2016 by a gentleman named Kent Russell, a really nice guy, and his goal was to figure out ways to incorporate React and JSX into Shiny applications, and among other things, the package before we started working on it, it had React HTML dependencies, React and React DOM, and so it is the canonical place in the R package ecosystem where React stuff is currently being hung. He also did something really neat in his package.
He embeds V8, the JavaScript engine, to support JSX strings inside R. It's pretty wild, but it basically means that you can write JSX without installing any JavaScript build tools, so that's a neat thing, and Kent's done a lot with that.
The enhancements that I'm demonstrating now have a more specific goal than the original package goal, which is to make HTML widgets in particular easier, and the idea to do this, it was either Joe or JJ, somebody in our studio before me, identified a symmetry between React's API and the API of HTML widgets and thought, huh, we have an opportunity here to bridge these two worlds in maybe an elegant way, or at least a way that would prevent people from writing lots of code, and the third goal is we want to, like I said, prescribe and support and document workflows and tool chains for those who are not as intimately familiar with the JavaScript ecosystem.
Making an HTML widget with reactR
So to make an HTML widget using everything I just told you about, you would first scaffold an R package with the use this package. Use this amazing package. It has a function in it called create underscore package, and it will build out an empty skeletal package. Then you can call React R colon colon scaffold React widget while you're inside that package you just scaffolded, and it will populate with JavaScript build tool configurations that we will support and condone, and then finally, you do need to install Yarn and Webpack on your machine, but once you do, then you can install these tools and they'll pick up that configuration we generated for you, and at the end of the day, you'll have a minimum viable working HTML widget with React in it.
Remaining limitations and future work
We do have some remaining work ahead of us, so I would prepare you as you begin on your React journey that there are some limitations currently. We haven't figured out a really nice way of sending data or at least supporting widget authors to send data from the browser context to the R context. This is not impossible right now, and in fact, nothing I'm showing you was impossible before my talk, because all of it really just was a factor of how much JavaScript you were willing to write, so this is a case where sending values from a React base HTML widget to R, not impossible, but as of right now, you're going to need to write some JavaScript that relies on this existing Shiny feature on input change.
We made some interesting prototypes to support this without additional JavaScript, and I think these ideas hold some promise, so over the coming weeks, days, months, we're going to be iterating on that, and again, this is why it would be so awesome if you're interested in this to get involved and try it out and let us know what would feel natural to you, because at the end of the day, this is all about supporting ease of use and accessibility.
All right. So that's all the material I have prepared. I think I'll have quite a few time for questions. I would like to make a special thanks to Kent Russell, who's been such a great package maintainer, and maybe I could call him a friend at this point. I haven't met him in person. A lot of emails, but I hope he's cool with that. So thank you, Kent. Thank you all very much.
Q&A
We do have some time for questions, so let me know, and I'll throw you the ah.
It's funny when you go to a talk and it covers something that you already were dying to learn about. So thank you very much. However, the problem is that I have a similar mapping library sort of application, but it's from Vue. I'm not sure how to phrase this. How much work is it to create this React R package, and do you think it's very likely that something would be recreated for Vue?
So first of all, great point. Second of all, we should hang out. Maybe we can be friends. Third, we think very highly of Vue within our studio, and I say that's kind of the collective because I don't have personal experience with it, but we have several experience reports internally of successes. We chose React initially because there was already an existing package and someone in the community we could work with on it, and because it seems like, I could be wrong, but my impression is there are far more available libraries in React world than in Vue world as of this moment. I could be wrong about that, but that's kind of my impression.
So to answer that specific technical question, I think there are as few, if not fewer, technical hurdles in Vue as there are in React. I mentioned the symmetry between HTML widgets and React. I believe there is that same symmetry based on what I know right now between HTML widgets and Vue. So it's something we've identified and we really want to do at some point in the future. Thank you.
Hi. I had a question about there's this library that you guys have called crosstalk. I'm not sure if you're familiar with it. What it does is if you have some data that you want to filter on the frontend, you can add a plotly and you can add a data table and you can add some dropdowns and it does all of those filtering very quickly for you on the frontend. I don't know if work is being actively done on that package, but when I was looking at the stuff you were doing with the React, I was wondering if that sort of frontend filtering and aggregation is something that you guys have planned for Reactor.
So we haven't worked on that specifically, but it is one of our goals to be what I think of as well-behaved members of the HTML widgets ecosystem. There are some cases where we're going to sacrifice capabilities for ease of use. So I mentioned that there's a lot of scaffolding involved to get people going quickly. I think crosstalk is one of those cases where it would be very difficult for us to scaffold a general approach. So JavaScript would be involved, but it's certainly not something we would rule out or otherwise make impossible. So it would always be possible. It just may involve more JavaScript than I showed.
Yeah. Would there be any limitations on the React components as to compatibility? For example, something that does too much in React that you wouldn't be able to support?
Excellent question. Yes. So we made some cuts there, again, in the interest of ease of use. There are certain things you can do in React that don't really follow from the model that we advocate. We settle on the model we have because it's a set of conventions for interopting with React that seem to work for a majority of libraries. There are those edge cases, and when you hit the edge cases, it's kind of like the crosstalk story. You need to know JavaScript then at that point. But again, when you do get to that point, our goal is to at least have examples and documentation to support you as you go that direction in JavaScript world so that it's never totally inaccessible to you, that you identify while you're building your widget that that's a step, a bridge you need to cross, and we're there to hold your hand at least while you do that.

