` react component instead of an HTML ``, we could simply change:
-```{R eval = FALSE}
-server <- function(input, output, session) {
- output$widgetOutput <- renderReactSparklines(
- reactSparklines("Hello world!")
- )
-}
+```r
+content <- htmltools::tag("div", list(message))
```
-In the code above, `renderReactSparklines` expects to receive the return value of `reactSparklines` as its argument.
+to
-`reactSparklines` is a thin wrapper around `htmlwidgets::createWidget`. Its most important argument, `message`, is the one we must change the handling of. In the current implementation, the following happens to `message`:
-
-```{R eval = FALSE}
-component <- reactR::reactMarkup(htmltools::tag("div", list(message)))
+```r
+reactR::component("Sparklines", list(message))
```
-1. We wrap `message` in a list
-1. We call `htmltools::tag` to create a `div` with the list we created as its children
-1. We call `reactR::reactMarkup` to prepare the tag to be rendered in the browser
-1. We assign to `component`
-
-Then, we pass `component` as the second argument of `htmlwidgets::createWidget`.
-
-Widgets created using reactR expect for this argument to be a representation of `markup`, or either an `htmltools::tag` or a `reactR::component`. When we called `reactR.reactWidget` in our JavaScript, we created and installed the browser-side implementation of a widget that expects to receive markup and then renders that markup in the widget's HTML container.
-
-Let's modify the `reactSparklines` function so that it handles `message` differently. In fact, let's change the meaning of that argument completely. Instead of a `message`, it should take an argument `data`, which is the vector of numbers to display as a sparkline graph:
-
-```{r eval = FALSE}
-reactSparklines <- function(data, width = NULL, height = NULL, elementId = NULL) {
+Remember, though, that we'd like `` to consume a `data` property and also accept other valid components (e.g., ``, ``, etc) from this library as children. So, we could change the body and signature of `sparklines()` in the following way:
+```{r}
+sparklines <- function(data, ..., width = NULL, height = NULL) {
+
# describe a React component to send to the browser for rendering.
- component <- reactR::reactMarkup(reactR::component(
+ content <- reactR::component(
"Sparklines",
- list(data = data, reactR::component("SparklinesLine"))
- ))
-
+ list(data = data, ...)
+ )
+
# create widget
htmlwidgets::createWidget(
- name = 'reactSparklines',
- component,
+ name = 'sparklines',
+ reactR::reactMarkup(content),
width = width,
height = height,
- package = 'reactSparklines',
- elementId = elementId
+ package = 'sparklines'
)
}
```
-Now, we're using the `data` argument in a more sophisticated way. We're assigning it to the attribute `data` of the `Sparklines` component, as per the first example in the [react-sparklines documentation](http://borisyankov.github.io/react-sparklines/). Then, we create a `SparklinesLine` component to tell `react-sparklines` the format to display the data.
+At this point, we define functions that make it easy for the user to create the other components by adding these to the `R/reactSparklines.R`
-Essentially, we're using R code that corresponds directly to the [JSX](https://reactjs.org/docs/introducing-jsx.html) syntax in the `react-sparklines` examples. This is a major benefit of using reactR: examples in JSX are generally easy to adapt.
+```{r}
+#' @export
+sparklinesLine <- function(...) {
+ reactR::React$SparklinesLine(...)
+}
-Our widget now assumes that `data` is a numeric vector, and relies on the fact that this vector becomes a JavaScript array once it's sent to the browser.
+#' @export
+sparklinesSpots <- function(...) {
+ reactR::React$SparklinesSpots(...)
+}
+```
-After you've edited `R/reactSparklines.R`, run `devtools::install(quick = TRUE)` or hit `Ctrl-Shift-B` (macOS: `Cmd-Shift-B) to rebuild the package.
+### JavaScript changes
-## Trying it out
+In order for the **reactR** toolchain to know how to render components from the 'react-sparklines' library, we need to essentially register the react components on the JavaScript side. This can be done in the `srcjs/sparklines.js` file which currently looks like this:
-It's finally time to modify `app.R` and test our widget modifications out. Open `app.R`, it should look like this:
+```{js}
+import { reactWidget } from 'reactR';
-```{r eval = FALSE}
-library(shiny)
-library(reactSparklines)
+reactWidget('sparklines', 'output', {});
+```
-ui <- fluidPage(
- titlePanel("reactR HTMLWidget Example"),
- reactSparklinesOutput('widgetOutput')
-)
+First, `reactWidget` is [imported](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) from the `'reactR'` JavaScript module. This function will essentially register the react components that we want inside the **reactR** and **htmlwidgets** toolchain. Note that the `'reactR'` JS module is as an html dependency, but webpack is configured in `webpack.config.js` to consider it a module, so it's available to us here.
-server <- function(input, output, session) {
- output$widgetOutput <- renderReactSparklines(
- reactSparklines("Hello world!")
- )
-}
+Then, there's a call to `reactWidget`, and we pass it three arguments:
-shinyApp(ui, server)
+1. The name of the widget (`'sparklines'`)
+1. The type of the widget (`'output'`)
+1. The React components that should be exposed to the widget. In this template, we didn't have to include any because it's just rendering an HTML div.
+
+Instead of passing an empty object (`{}`) as the React components, we provide an object with all the components we need from the 'react-sparklines' module:
+
+```{js}
+import { Sparklines, SparklinesLine, SparklinesSpots } from 'react-sparklines';
+import { reactWidget } from 'reactR';
+
+reactWidget('sparklines', 'output', {
+ Sparklines: Sparklines,
+ SparklinesLine: SparklinesLine,
+ SparklinesSpots: SparklinesSpots
+});
```
-The thing we need to change is the argument to `reactSparklines`. It should no longer be a string, but a numeric vector to display as a sparkline graph. Here is the amended code:
+### Go for a spin
+
+Now that we've made the necessary changes to the JavaScript and R source code, it's time to compile the JavaScript, install the R package
+
+```bash
+# TODO: maybe we could provide a Makefile to compile JS and install R pkg?
+yarn install
+yarn run webpack --mode=development
+Rscript -e "devtools::document(); devtools::install(); sparklines::sparklines(rnorm(10))"
+```
-```{r eval = FALSE}
+This should open up the `sparklines()` widget in your browser. If it does, congratulations, you just wrote your first React-based widget!
+
+### Shiny integration
+
+The scaffolding template already provides the glue you need to get your **reactR** widget to render in **shiny**. The two relevant functions are `renderSparklines()` and `sparklinesOutput()`. You shouldn't need to modify these functions -- they should work out of the box. You will, however, want to modify the example **shiny** app provided by the in the `app.R` file:
+
+```{r}
library(shiny)
-library(reactSparklines)
+library(sparklines)
ui <- fluidPage(
titlePanel("reactR HTMLWidget Example"),
- reactSparklinesOutput('widgetOutput')
+ sparklinesOutput('myWidget')
)
server <- function(input, output, session) {
- output$widgetOutput <- renderReactSparklines(
- reactSparklines(sample.int(10, 10))
- )
+ output$myWidget <- rendersparklines({
+ sparklines(
+ data = rnorm(10),
+ sparklinesLine(color = "#56b45d"),
+ sparklinesSpots(style = list(fill = "#56b45d"))
+ )
+ })
}
shinyApp(ui, server)
```
-Now, when you run `app.R`, you should see something like the following:
-
-```{r echo=FALSE}
-knitr::include_graphics('./widget_app_improved.jpg')
-```
-
-Congratulations, you just wrote your first React-based widget!
-
-Another thing you can try is running `reactSparklines(data = sample.int(10, 10))` directly in the RStudio Console. You should see a sparkline graph appear in the Viewer.
+Now, when you run `shiny::runApp()`, you should see your vision become reality!
-## Next steps
+## Further learning
-We've reached the end of this tutorial, but if you'd like to see how a sparklines library could be further improved, you might be interested in our [sparklines-example](https://github.com/react-R/sparklines-example) project. It picks up where we leave off, by creating a kind of DSL that makes the other sparkline types easily accessible from R.
+This tutorial walked you through the steps taken you create an R interface to the react-sparklines library. The full example package is accessible at . Our intention is keep creating example packages under the profile, so head there if you'd like to see example of interfacing to other react libraries.