From f4327b95bef4b38f31968f7fea4206b220731091 Mon Sep 17 00:00:00 2001 From: xari Date: Tue, 23 Feb 2021 00:15:35 +0100 Subject: [PATCH 1/4] started intro revision --- vignettes/intro_reactR.Rmd | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/vignettes/intro_reactR.Rmd b/vignettes/intro_reactR.Rmd index 20f4f8a..c3a4e63 100644 --- a/vignettes/intro_reactR.Rmd +++ b/vignettes/intro_reactR.Rmd @@ -1,6 +1,6 @@ --- title: "Intro to reactR" -author: "Kent Russell" +author: "Kent Russell & Harry Anderson" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > @@ -9,11 +9,22 @@ vignette: > %\VignetteEncoding{UTF-8} --- -## Why reactR? +## Why reactR -[`react`](https://reactjs.org/) has become incredibly popular, and the ecosystem around `react` is robust. `reactR` aims to allow `R` users to more easily incorporate `react` and `JSX`. +[`React`](https://reactjs.org/) is a JavaScript library for building user interfaces. +The `{shiny}` package provides us with functions like `sliderInput()` and `selectInput()` to help us to easily implement common UI features in our Shiny apps. +These functions are easy to use, and _most_ of the time they'll be all we need to build-out our prototypes. +But seasoned web developers know that there's a world of UI potential beyond what `{shiny}` gives us out-of-the-box, and while packages like `[{shinydashboard}](https://github.com/rstudio/shinydashboard)` expand the libary of UI elements at our disposal, they only go so far. -## Install +The React ecosystem, on the other hand, has every piece of UI that we could ever imagine. +The only problem is that React is a JavaScript (not an R) library. +Enter: `{reactR}`, which binds React components to R functions, and makes our Shiny apps really shine. + +If you don't know anything about React, then you should brush-up on it by going through the [official tutorial](https://reactjs.org/tutorial/tutorial.html). +You'll need to be familliar with the basics of JavaScript modules, React components and JSX in order to properly understand the rest of this tutorial. + + +## Installation ``` install.packages("reactR") @@ -23,9 +34,10 @@ install.packages("reactR") # devtools::install_github("timelyportfolio/reactR") ``` -## Quick Example +--- -Let's use `react` to render a simple `h1` HTML element below. +## A quick example +### Using React to render a simple `h1` HTML element below
@@ -50,6 +62,15 @@ attachDependencies( ) ``` +--- + +## A complex example +### Creating our own React component, and integrating it into a Shiny app + +## Requirements + +In addition to having our Shiny development environment up-and-running, we'll also need to have [Node and NPM](https://nodejs.org/en/download/) installed. + ## Blog Post For more on how we can use R and React, see the blog post [React in R](https://www.jsinr.me/2017/11/19/react-in-r/). Also, there are many more examples in the Github repo at [inst/examples](https://github.com/react-R/reactR/tree/master/inst/examples). From 9349e6180eb5c2221064776f36a147bfc76493ef Mon Sep 17 00:00:00 2001 From: xari Date: Wed, 24 Feb 2021 15:47:35 +0100 Subject: [PATCH 2/4] Expanded intro and added GIF --- vignettes/intro_reactR.Rmd | 73 +++++++++++++++++++++---------------- vignettes/time_picker.gif | Bin 0 -> 10117 bytes 2 files changed, 41 insertions(+), 32 deletions(-) create mode 100644 vignettes/time_picker.gif diff --git a/vignettes/intro_reactR.Rmd b/vignettes/intro_reactR.Rmd index c3a4e63..a0c6442 100644 --- a/vignettes/intro_reactR.Rmd +++ b/vignettes/intro_reactR.Rmd @@ -18,13 +18,15 @@ But seasoned web developers know that there's a world of UI potential beyond wha The React ecosystem, on the other hand, has every piece of UI that we could ever imagine. The only problem is that React is a JavaScript (not an R) library. -Enter: `{reactR}`, which binds React components to R functions, and makes our Shiny apps really shine. +Enter: `{reactR}`, which lets us bind React components to R functions. -If you don't know anything about React, then you should brush-up on it by going through the [official tutorial](https://reactjs.org/tutorial/tutorial.html). -You'll need to be familliar with the basics of JavaScript modules, React components and JSX in order to properly understand the rest of this tutorial. +> `{reactR}` gives us the power to use any React component in our Shiny apps. +If you don't know anything about React, then you may want to brush-up on it by going through the [official tutorial](https://reactjs.org/tutorial/tutorial.html). +However, you won't need to know how to write JS code to use reactR. +Simply look-up a component that you'd like to use, and then follow the steps below to implement it in R. -## Installation +## Installing reactR ``` install.packages("reactR") @@ -34,47 +36,54 @@ install.packages("reactR") # devtools::install_github("timelyportfolio/reactR") ``` ---- - ## A quick example -### Using React to render a simple `h1` HTML element below +### Using reactR to render the `react-time-picker` input -
+`react-time-picker` is a react component that renders a time-picker input. +Neither `{shiny}`, nor any other prominent Shiny ecosystem package gives us a time-picker Shiny input, but using `{reactR}`, we're going to create a time-picker input that we can use in a Shiny app. +The code below creates an `htmlDependency` for the `react-time-picker` NPM package. ```{r} library(reactR) library(htmltools) -attachDependencies( - tags$script( - " - ReactDOM.render( - React.createElement( - 'h1', - null, - 'Powered by React' - ), - document.getElementById('react-heading-here') - ) - " - ), - html_dependency_react() +time_picker <- htmlDependency( + name = "react-time-picker", + version = "5.23.0", + src = c(href="https://unpkg.com/react-time-picker/dist"), + script = "entry.js", + stylesheet = "TimePicker.css" ) -``` ---- - -## A complex example -### Creating our own React component, and integrating it into a Shiny app +browsable( + tagList( + html_dependency_react(offline=FALSE), + time_picker, + tags$div(id="time-picker-wrapper"), + tags$script(HTML(babel_transform( +" +ReactDOM.render( setValue(newTime)} + value={value} + { ...configuration } />, document.querySelector('#time-picker-wrapper')) +" + ))) + ) +) +``` -## Requirements +![](./time-picker.gif) -In addition to having our Shiny development environment up-and-running, we'll also need to have [Node and NPM](https://nodejs.org/en/download/) installed. +The example above shows us how we can quickly make use of existing React components in R using `{reactR}`, but what we've seen in this introduction is actually just the tip of the iceberg for what we can accomplish with `{reactR}`. +In fact, you can even develop your own Shiny inputs that are based on React components like the one above. +The resources below will help you to get on your way to integrating React in your R projects: -## Blog Post +* [Video: Integrating React.js and Shiny](https://rstudio.com/resources/rstudioconf-2019/integrating-react-js-and-shiny/) +* [Blog post: React in R](https://www.jsinr.me/2017/11/19/react-in-r/) -For more on how we can use R and React, see the blog post [React in R](https://www.jsinr.me/2017/11/19/react-in-r/). Also, there are many more examples in the Github repo at [inst/examples](https://github.com/react-R/reactR/tree/master/inst/examples). +You can also find more examples of reactR at work in the Github repo at [inst/examples](https://github.com/react-R/reactR/tree/master/inst/examples). ## Using JSX -[`JSX`](https://reactjs.org/docs/jsx-in-depth.html) helps ease some of the burden caused by `React.createElement`. `reactR` provides a `babel_transform()` function to use `JSX`. Hopefully, in the future, we can convince RStudio to modify `htmltools` to work directly with `JSX` (see [issue](https://github.com/rstudio/htmltools/pull/72)). +[`JSX`](https://reactjs.org/docs/jsx-in-depth.html) helps ease some of the burden caused by `React.createElement`. +`reactR` provides a `babel_transform()` function to use `JSX`. +Hopefully, in the future, we can convince RStudio to modify `htmltools` to work directly with `JSX` (see [issue](https://github.com/rstudio/htmltools/pull/72)). diff --git a/vignettes/time_picker.gif b/vignettes/time_picker.gif new file mode 100644 index 0000000000000000000000000000000000000000..45fa141fcc2a222b1ad19f5820dc63309a5388e7 GIT binary patch literal 10117 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 t@q Date: Mon, 8 Mar 2021 23:21:36 +0100 Subject: [PATCH 3/4] Elaborated on the basic example --- vignettes/intro_reactR.Rmd | 114 +++++++++++++++++++++++++++---------- 1 file changed, 84 insertions(+), 30 deletions(-) diff --git a/vignettes/intro_reactR.Rmd b/vignettes/intro_reactR.Rmd index a0c6442..0405868 100644 --- a/vignettes/intro_reactR.Rmd +++ b/vignettes/intro_reactR.Rmd @@ -12,19 +12,21 @@ vignette: > ## Why reactR [`React`](https://reactjs.org/) is a JavaScript library for building user interfaces. -The `{shiny}` package provides us with functions like `sliderInput()` and `selectInput()` to help us to easily implement common UI features in our Shiny apps. -These functions are easy to use, and _most_ of the time they'll be all we need to build-out our prototypes. -But seasoned web developers know that there's a world of UI potential beyond what `{shiny}` gives us out-of-the-box, and while packages like `[{shinydashboard}](https://github.com/rstudio/shinydashboard)` expand the libary of UI elements at our disposal, they only go so far. +When developing Shiny apps, we use functions from the `{shiny}` package like `sliderInput()` and `selectInput()` to help us to easily implement common UI features in our Shiny apps. +When we build and launch our Shiny apps, the R code that we write gets compiled to HTML, CSS and JavaScript —the three key languages in web development —and these `{shiny}` UI functions render the simple HTML elements that make up the user-interface of our apps. -The React ecosystem, on the other hand, has every piece of UI that we could ever imagine. -The only problem is that React is a JavaScript (not an R) library. -Enter: `{reactR}`, which lets us bind React components to R functions. +Most of the time, these functions will be enough to build-out our prototypes, but they are limited in what they offer, and seasoned web developers know that there's a world of UI potential beyond what `{shiny}` gives us out-of-the-box. +While packages like `[{shinydashboard}](https://github.com/rstudio/shinydashboard)` expand the libary of UI elements at our disposal, they too have their limitations. +The React ecosystem, on the other hand, has a package for every piece of UI that we could ever imagine. +Of course, working with React means working with JavaScript. +Thankfully `{reactR}` exists to bind React components to R functions, so even if we don't know JavaScript, we can still use React components in our Shiny apps. -> `{reactR}` gives us the power to use any React component in our Shiny apps. +Additionally, developers who already know JavaScript may find it more natural to create custom pieces of UI in React than directly in Shiny. +In this way, `{reactR}` makes it possible for each member of a mixed data-science/web-development team to contribute to their fullest potential on a Shiny project. -If you don't know anything about React, then you may want to brush-up on it by going through the [official tutorial](https://reactjs.org/tutorial/tutorial.html). -However, you won't need to know how to write JS code to use reactR. -Simply look-up a component that you'd like to use, and then follow the steps below to implement it in R. +If you don't know anything about React, you may benefit from brushing-up on the basics with the [official tutorial](https://reactjs.org/tutorial/tutorial.html). +This will help you to understand the non-R syntax that you'll see in this tutorial. +But if you don't have time to read-up on React, don't sweat it; simply look-up the component that you'd like to use, and follow the steps below to include it in your Shiny app. ## Installing reactR @@ -37,16 +39,59 @@ install.packages("reactR") ``` ## A quick example -### Using reactR to render the `react-time-picker` input +### Rendering an H1 tag -`react-time-picker` is a react component that renders a time-picker input. -Neither `{shiny}`, nor any other prominent Shiny ecosystem package gives us a time-picker Shiny input, but using `{reactR}`, we're going to create a time-picker input that we can use in a Shiny app. -The code below creates an `htmlDependency` for the `react-time-picker` NPM package. +The code below will attach some JavaScript to the page. +These lines of JS will create an H1 element, and insert it at the place on the page where the div with the ID "beef" is. +The text content of the H1 will read _"Powered by React"_. -```{r} +```html +
+``` + +```r library(reactR) library(htmltools) +attachDependencies( + tags$script( + " + ReactDOM.render( + React.createElement( + 'h1', + null, + 'Powered by React' + ), + document.getElementById('beef') + ) + " + ), + html_dependency_react() +) +``` + +Obviously, rendering an H1 tag can already easily be done via `h1("Powered by React")`. +The point of the above example is to familliarize ourselves with the arcitecture of how to write React code within an R environment. +Particularly, it's important to note how we're using the `attachDependencies()` function to insert some JS into the page. + +Let's explore a slightly more complex example next. + +### Using `{reactR}` to render the `react-time-picker` input + +In this next example, we're going to render an existing React component into the page. +This component comes from the `react-time-picker` NPM package, and it renders a "time-picker" input. +NPM stands for "Node Package Manager", and it is the package registry where you can find most React packages. +Think of it like CRAN, for React. + +We can see a demo of this input in-action below. + +![](./time-picker.gif) + +`{shiny}` doesn't ship a `timePickerInput()` function, and nor does `{shinyDashboard}`, so this is the kind of situation where it makes sense to reach for `{reactR}`. +In order to get it up-and-running, we'll first need to create an _HTML dependency_ for the `react-time-picker` CSS and JS code. +The CSS is necessary for the input to "look" as it should, once it is rendered on the page. + +```r time_picker <- htmlDependency( name = "react-time-picker", version = "5.23.0", @@ -54,27 +99,36 @@ time_picker <- htmlDependency( script = "entry.js", stylesheet = "TimePicker.css" ) +``` + +The URL that we see above is where the package files are hosted, and the `script` and `stylesheet` arguments indicate where to look for the JS and CSS exports. + +Let's not forget to add the HTML marker for where we want the input to be inserted... -browsable( - tagList( - html_dependency_react(offline=FALSE), - time_picker, - tags$div(id="time-picker-wrapper"), - tags$script(HTML(babel_transform( -" -ReactDOM.render( setValue(newTime)} +```html +
+``` + +=== Help needed here! === + +```r +attachDependencies( + tags$script( + " + ReactDOM.render( + setValue(newTime)} value={value} - { ...configuration } />, document.querySelector('#time-picker-wrapper')) -" - ))) - ) + { ...configuration } />, + document.getElementById('insert-time-picker-here') + ) + " + ), + html_dependency_react() ) ``` -![](./time-picker.gif) - The example above shows us how we can quickly make use of existing React components in R using `{reactR}`, but what we've seen in this introduction is actually just the tip of the iceberg for what we can accomplish with `{reactR}`. -In fact, you can even develop your own Shiny inputs that are based on React components like the one above. +In fact, you can even develop your own Shiny input functions that are based on React components like the one above. The resources below will help you to get on your way to integrating React in your R projects: * [Video: Integrating React.js and Shiny](https://rstudio.com/resources/rstudioconf-2019/integrating-react-js-and-shiny/) From 6d9deb1e91009116f7024e59cd8235ca4e3a6f2e Mon Sep 17 00:00:00 2001 From: xari Date: Fri, 19 Mar 2021 17:43:40 +0100 Subject: [PATCH 4/4] added section about JSX --- vignettes/intro_reactR.Rmd | 110 +++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 53 deletions(-) diff --git a/vignettes/intro_reactR.Rmd b/vignettes/intro_reactR.Rmd index 0405868..0237e6c 100644 --- a/vignettes/intro_reactR.Rmd +++ b/vignettes/intro_reactR.Rmd @@ -26,12 +26,11 @@ In this way, `{reactR}` makes it possible for each member of a mixed data-scienc If you don't know anything about React, you may benefit from brushing-up on the basics with the [official tutorial](https://reactjs.org/tutorial/tutorial.html). This will help you to understand the non-R syntax that you'll see in this tutorial. -But if you don't have time to read-up on React, don't sweat it; simply look-up the component that you'd like to use, and follow the steps below to include it in your Shiny app. ## Installing reactR -``` -install.packages("reactR") +```{r} +install.packages("reactR", repos = "http://cran.us.r-project.org") # for the latest development version # install from Github @@ -45,14 +44,14 @@ The code below will attach some JavaScript to the page. These lines of JS will create an H1 element, and insert it at the place on the page where the div with the ID "beef" is. The text content of the H1 will read _"Powered by React"_. -```html -
-``` - -```r -library(reactR) +```{r} library(htmltools) +library(reactR) + +div(id="beef") +``` +```{r} attachDependencies( tags$script( " @@ -66,7 +65,7 @@ attachDependencies( ) " ), - html_dependency_react() + html_dependency_react() # The script above depends on the React library ) ``` @@ -74,70 +73,75 @@ Obviously, rendering an H1 tag can already easily be done via `h1("Powered by Re The point of the above example is to familliarize ourselves with the arcitecture of how to write React code within an R environment. Particularly, it's important to note how we're using the `attachDependencies()` function to insert some JS into the page. -Let's explore a slightly more complex example next. +## Using JSX -### Using `{reactR}` to render the `react-time-picker` input +JSX goes hand-in-hand with React. +It allows us to express React components as HTML-like tags. +In other words, instead of using `React.createElement(SomeReactComponent)` whenever we need to create a new element, we can simply wrap the component name in tags, ``, and omit the call to `React.createElement()`. -In this next example, we're going to render an existing React component into the page. -This component comes from the `react-time-picker` NPM package, and it renders a "time-picker" input. -NPM stands for "Node Package Manager", and it is the package registry where you can find most React packages. -Think of it like CRAN, for React. +Without getting into the nitty-gritty of how to use JSX, let's simply focus on how to use JSX with reactR. -We can see a demo of this input in-action below. +Let's create the same H1 tag as in the last example, but this time we'll do it in JSX, using the `babel_transform()` function from `{reactR}`. -![](./time-picker.gif) +```{r} +div(id="penguin") +``` -`{shiny}` doesn't ship a `timePickerInput()` function, and nor does `{shinyDashboard}`, so this is the kind of situation where it makes sense to reach for `{reactR}`. -In order to get it up-and-running, we'll first need to create an _HTML dependency_ for the `react-time-picker` CSS and JS code. -The CSS is necessary for the input to "look" as it should, once it is rendered on the page. +Don't forget to first install the `{V8}` package, otherwise `{babel_transform()}` won't work. -```r -time_picker <- htmlDependency( - name = "react-time-picker", - version = "5.23.0", - src = c(href="https://unpkg.com/react-time-picker/dist"), - script = "entry.js", - stylesheet = "TimePicker.css" -) +```{r echo=FALSE} +install.packages("V8", repos="http://cran.us.r-project.org") ``` -The URL that we see above is where the package files are hosted, and the `script` and `stylesheet` arguments indicate where to look for the JS and CSS exports. +The code-chunk below will generate the call to `React.createElement()` for us and store it in a variable that we'll use to render the H1 in the following code chunk. + +```{r} +library(stringr) -Let's not forget to add the HTML marker for where we want the input to be inserted... +the_transformed_jsx <- + babel_transform("ReactDOM.render( +

Powered by React

, + document.getElementById('penguin'))") -```html -
+the_transformed_jsx ``` -=== Help needed here! === +Now that we have the transformed string of JavaScript code, we can attach it to our document, as shown below: -```r +```{r} attachDependencies( - tags$script( - " - ReactDOM.render( - setValue(newTime)} - value={value} - { ...configuration } />, - document.getElementById('insert-time-picker-here') - ) - " - ), + tags$script(the_transformed_jsx), html_dependency_react() ) ``` -The example above shows us how we can quickly make use of existing React components in R using `{reactR}`, but what we've seen in this introduction is actually just the tip of the iceberg for what we can accomplish with `{reactR}`. -In fact, you can even develop your own Shiny input functions that are based on React components like the one above. -The resources below will help you to get on your way to integrating React in your R projects: +> Hopefully, in the future, we can convince RStudio to modify `htmltools` to work directly with `JSX` (see [issue](https://github.com/rstudio/htmltools/pull/72)). + +## The bigger picture + +While it is possible to use `{reactR}` to write JSX and React code directly inside of R code, doing so is __currently__ limited, and you will likely encounter numerous hurdles when trying to use state, or even include someone else's component in your code. + +Where `{reactR}` really shines though, is when you use it to create HTML widgets and custom Shiny inputs. + +For example, if you wanted to use a time-picker input in your Shiny app (like the one below), you could create one using the functions that reactR provides. + +![](./time_picker.gif) + +The article titled [Authoring inputs powered by React with reactR](https://react-r.github.io/reactR/articles/intro_inputs.html) will walk you through how to take a React component from an NPM package, and package it into a custom Shiny input. + +Similarly, if Shiny isn't your bag, you can package React code as a custom HTML Widget. +For that, [Authoring htmlwidgets powered by React with reactR](https://react-r.github.io/reactR/articles/intro_htmlwidgets.html) will be your guide. + +> NPM stands for "Node Package Manager", and it is the package registry where you can find most React packages. +> Think of it like CRAN, for React. + +In addition to the articeles mentioned above, the resources below will help you to get on your way to integrating React in your R projects: * [Video: Integrating React.js and Shiny](https://rstudio.com/resources/rstudioconf-2019/integrating-react-js-and-shiny/) * [Blog post: React in R](https://www.jsinr.me/2017/11/19/react-in-r/) You can also find more examples of reactR at work in the Github repo at [inst/examples](https://github.com/react-R/reactR/tree/master/inst/examples). -## Using JSX - -[`JSX`](https://reactjs.org/docs/jsx-in-depth.html) helps ease some of the burden caused by `React.createElement`. -`reactR` provides a `babel_transform()` function to use `JSX`. -Hopefully, in the future, we can convince RStudio to modify `htmltools` to work directly with `JSX` (see [issue](https://github.com/rstudio/htmltools/pull/72)). +React is a very useful tool for composing complex UIs, and the reactR package makes the power of React available to R users. +This makes it even more possible to have software engineers and data scientists collaborate on the same production applications, leveraging the expertise of each to create better tools for their communities. +We think this package has huge potential, and we hope that you will too.