Skip to content

Commit 30f81e5

Browse files
committed
Add input vignette and screenshots
1 parent 37a58a8 commit 30f81e5

File tree

4 files changed

+256
-0
lines changed

4 files changed

+256
-0
lines changed

vignettes/input_app.jpg

16 KB
Loading

vignettes/input_sketchpicker.jpg

16.7 KB
Loading
31.7 KB
Loading

vignettes/intro_inputs.Rmd

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
---
2+
title: "Authoring inputs powered by React with reactR"
3+
author:
4+
- Alan Dipert
5+
date: "`r Sys.Date()`"
6+
output: rmarkdown::html_vignette
7+
vignette: >
8+
%\VignetteIndexEntry{Shiny inputs with reactR}
9+
%\VignetteEngine{knitr::rmarkdown}
10+
%\VignetteEncoding{UTF-8}
11+
---
12+
13+
```{r, echo=FALSE, include=FALSE}
14+
knitr::opts_chunk$set(eval = FALSE)
15+
```
16+
17+
[Shiny](http://shiny.rstudio.com/) comes with a large library of input
18+
[widgets](https://shiny.rstudio.com/gallery/widget-gallery.html) for collecting
19+
input from the user and conveying input data to R.
20+
21+
If you want a kind of input *not* provided by Shiny — like a color picker,
22+
or a different kind of slider — you've always been able to build your own.
23+
Shiny's input system is
24+
[extensible](https://shiny.rstudio.com/articles/building-inputs.html). All
25+
that's required is an understanding of certain conventions and a little custom
26+
JavaScript.
27+
28+
reactR provides additional tools to ease the creation of new Shiny inputs
29+
implemented using React. In the following tutorial, we will demonstrate these
30+
tools by implementing a new Shiny color picker input that wraps the
31+
[react-color](https://github.com/casesandberg/react-color) library.
32+
33+
## Software pre-requisites
34+
35+
In order to develop a **reactR** Shiny input, you'll need to install R and
36+
optionally RStudio. If you're on Windows, you should also install
37+
[Rtools](https://cran.r-project.org/bin/windows/Rtools/).
38+
39+
> For an excellent general introduction to R package concepts, check out the [R
40+
> packages](http://r-pkgs.had.co.nz/) online book.
41+
42+
In addition, you'll need to install the following JavaScript tools on your
43+
machine:
44+
45+
* [Node.js](https://nodejs.org): JavaScript engine and runtime for development
46+
outside of browsers. Provides the `node` and `npm` commands.
47+
* [Yarn](https://yarnpkg.com/en/): Command-line dependency management tool,
48+
provides the `yarn` command.
49+
50+
To follow along in this vignette, you'll also need the following R packages:
51+
52+
```{r}
53+
install.packages(c("shiny", "devtools", "usethis", "reactR"))
54+
```
55+
56+
## Scaffolding
57+
58+
To create a new widget you can call `scaffoldReactInput` to generate the basic
59+
structure and build configuration. This function will:
60+
61+
* Create the .R, .js, and .json files required by your input;
62+
* If provided, take an [npm](https://www.npmjs.com/) package name and version as
63+
a named list with `name` and `version` elements. For example, the npm package
64+
`foo` at version `^1.2.0` would be expressed as `list(name = "foo", version =
65+
"^1.2.0")`. The package, if provided, will be added to the new widget's
66+
`package.json` as a build dependency.
67+
68+
The following R code will create an R package named **colorpicker**, then
69+
provide the templating for creating an input powered by the
70+
`react-color` library on npm:
71+
72+
```{r}
73+
# Create the R package
74+
usethis::create_package("~/colorpicker")
75+
# Inject the widget templating
76+
withr::with_dir(
77+
"~/colorpicker",
78+
reactR::scaffoldReactInput("colorpicker", list("react-color" = "^2.17.0"), edit = FALSE)
79+
)
80+
```
81+
82+
## Building and installing
83+
84+
### Building the JavaScript
85+
86+
The next step is to navigate to the newly-created `sparklines` project and run
87+
the following commands in the terminal:
88+
89+
```
90+
yarn install
91+
yarn run webpack
92+
```
93+
94+
* `yarn install` downloads all of the dependencies listed in `package.json` and
95+
creates a new file, `yarn.lock`. You should add this file to revision control.
96+
It will be updated whenever you change dependencies and run `yarn install`.
97+
**Note: you only need to run it after modifying package.json**. For further
98+
documentation on `yarn install`, see the [yarn
99+
documentation](https://yarnpkg.com/lang/en/docs/cli/install/).
100+
101+
* `yarn run webpack` compiles the [ES2015](https://babeljs.io/docs/en/learn/)
102+
JavaScript source file at `srcjs/colorpicker.jsx` into
103+
`www/colorpicker/colorpicker/colorpicker.js`. The latter file is the one
104+
actually used by the R package and includes all the relevant JavaScript
105+
dependencies in a dialect of JavaScript that most browsers understand.
106+
107+
`yarn run webpack` is not strictly a `yarn` command. In fact, `yarn run` simply
108+
delegates to the [webpack](https://webpack.js.org/) program. Webpack's
109+
configuration is generated by `scaffoldReactInput` in the file
110+
`webpack.config.js`, but you can always change this configuration and/or modify
111+
the `yarn run webpack` command to suit your needs.
112+
113+
### Installing the R package
114+
115+
Now that the input's JavaScript is compiled, go ahead and install the R
116+
package:
117+
118+
```{r}
119+
devtools::document()
120+
devtools::install(quick = TRUE)
121+
```
122+
123+
Alternatively, in RStudio, you can use the keyboard shortcuts `Ctrl+Shift+D` and
124+
`Ctrl-Shift-B` to document and build the package. (On macOS, the shortcuts are
125+
`Cmd+Shift+D` and `Cmd+Shift+B`)
126+
127+
## Run the included demo
128+
129+
Now that the input's JavaScript is compiled, and the R package is installed,
130+
run `app.R` to see a demo in action:
131+
132+
```{r}
133+
shiny::runApp()
134+
```
135+
136+
Alternatively, in RStudio, you can open `app.R` and press `Ctrl-Shift-Enter`
137+
(`Cmd-Shift-Enter` on macOS). You should see something like the following appear
138+
in the Viewer pane:
139+
140+
![](./input_app.jpg)
141+
142+
## Authoring a React input
143+
144+
At this point, we've built some scaffolding for an input powered by React.
145+
Let's modify it to create an interface to the `react-color` library.
146+
147+
### Connecting Shiny with React
148+
149+
Consider the following example taken from the [react-color
150+
documentation](http://casesandberg.github.io/react-color/).
151+
152+
```js
153+
import React from 'react';
154+
import { SketchPicker } from 'react-color';
155+
156+
class Component extends React.Component {
157+
158+
render() {
159+
return <SketchPicker />;
160+
}
161+
}
162+
```
163+
164+
That JavaScript code produces a `SketchPicker`-type interface that looks like
165+
this:
166+
167+
![](./input_sketchpicker.jpg)
168+
169+
However, that example doesn't demonstrate a way to default to a particular
170+
color, or a way to cause something to happen when the color changes. To
171+
accomplish these, `react-color` components can [optionally
172+
take](http://casesandberg.github.io/react-color/#api) the following
173+
[props](https://reactjs.org/docs/components-and-props.html):
174+
175+
* `color`: accepts a string of a hex color like `'#333'`
176+
* `onChangeComplete`: accepts a function taking a single argument, the new
177+
color, that will be called when the new color is selected
178+
179+
These operations are conceptually similar enough to the API expected of Shiny
180+
inputs that `reactR` can assist with mapping components to inputs.
181+
182+
It does so by introducing a convention for wrapping components like those
183+
provided by `react-color` with an intermediate component that accepts these
184+
props:
185+
186+
* `configuration`: A configuration object containing data from R used to
187+
parameterize the input's behavior
188+
* `value`: The input's values over time, beginning with the default
189+
* `setValue`: A function to call with the input's new value when one is created
190+
191+
The `configuration` and `value` props are initially populated on the R side, as
192+
arguments to the `createReactInput` function inside the input's constructor
193+
function. In the case of our newly-scaffolded input, that happens in
194+
`R/colorpicker.R`.
195+
196+
The `setValue` function is what causes new values to be sent to R, and also what
197+
triggers the "intermediate" component to repaint itself.
198+
199+
So, in order to make the components delivered by `react-color` accessible on the
200+
R side, we must create our own intermediate component that wraps one of
201+
`react-color`'s pickers.
202+
203+
### Create intermediate component
204+
205+
Open `srcjs/colorpicker.jsx` and paste the following in:
206+
207+
```js
208+
import { reactInput } from 'reactR';
209+
import { SketchPicker } from 'react-color';
210+
211+
const PickerInput = ({ configuration, value, setValue }) => {
212+
return (
213+
<SketchPicker
214+
color={ value }
215+
onChangeComplete={ color => setValue(color.hex) }
216+
/>
217+
);
218+
};
219+
220+
reactInput('.colorpicker', 'colorpicker', PickerInput);
221+
```
222+
223+
The above code creates a new [function
224+
component](https://reactjs.org/docs/components-and-props.html#function-and-class-components)
225+
called `PickerInput` that expects the props supplied by reactR and renders a
226+
parameterized `SketchPicker` from `react-color`. The `configuration` value is
227+
not yet used.
228+
229+
After saving the file, run `yarn run webpack` in the terminal and rebuild the
230+
package.
231+
232+
## Trying it out
233+
234+
After rebuilding the JavaScript and the package, try running `app.R` again. You
235+
should see something like this:
236+
237+
![](./input_sketchpicker_working.jpg)
238+
239+
When you select new colors, you should see the `textOutput` update accordingly.
240+
241+
You might have noticed that the input showed up initially without a color
242+
selected. That's because in `app.R` we didn't supply a `default` argument to the
243+
`colorpickerInput` function inside our `ui`.
244+
245+
Try replacing the call to `colorpickerInput` with this:
246+
`colorpickerInput("textInput", default = "#a76161")`
247+
248+
Now when you run the app, the color should start as a shade of red.
249+
250+
## Further learning
251+
252+
This tutorial walked you through the steps taken to wrap the `react-color`
253+
library in a Shiny input. The full example package is accessible at
254+
<https://github.com/react-R/colorpicker-example>. Our intention is keep creating
255+
example packages under the <https://github.com/react-R> organization, so head
256+
there if you'd like to see other examples of interfacing with React.

0 commit comments

Comments
 (0)