what-we-dev
Today we are going to build a React.js,
Highcharts.js, htmlwidget.R using
packer & highcharter.
create-pkg
We start by creating a package.
usethis::create_package("~/r_projects/react.highcharts")
init-widget
Once our package loads, we initialize a widget via packer.
packer::scaffold_widget("reactHC")
npm-install
Install React
- add react & babel
- add highcharts react
packer:::apply_react(FALSE)
packer::npm_install("highcharts-react-official",scope = "prod")
react-hc
Our first goal is to get to a reprex (reproducible example)
we can always improve it.
We add in the example react-highcharts code into the widget scaffolding.
import "widgets";
import React from "react";
import { render } from "react-dom";
import Highcharts from "highcharts";
import HighchartsReact from "highcharts-react-official";
HTMLWidgets.widget({
name: "reactHC",
type: "output",
factory: function (el, width, height) {
return {
renderValue: function (x) {
const App = () => (
<div>
<HighchartsReact highcharts={Highcharts} />
</div>
);
render(<App />, document.getElementById(el.id));
},
};
}
});
bundle-webpack
Bundle the Widget
document & install the R pkg
packer::bundle()
# ✓ Bundled
devtools::document()
devtools::install()
Hooray! Our React plot works!
react.highcharts::reactHC()
improving-it-a-bit
example-data
For this we will use the ggplot2 data set economics.
head(ggplot2::economics)
## # A tibble: 6 × 6
## date pce pop psavert uempmed unemploy
## <date> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1967-07-01 507. 198712 12.6 4.5 2944
## 2 1967-08-01 510. 198911 12.6 4.7 2945
## 3 1967-09-01 516. 199113 11.9 4.6 2958
## 4 1967-10-01 512. 199311 12.9 4.9 3143
## 5 1967-11-01 517. 199498 12.8 4.7 3066
## 6 1967-12-01 525. 199657 11.8 4.8 3018
highcharter
Within the existing R implementation - highcharter, we
can create a quick chart with a javascript legend placement, like the
below:
library(tidyverse)
library(highcharter)
hc <- economics_long %>%
mutate(date = datetime_to_timestamp(date)) %>%
hchart("area", hcaes(date, value01, group = variable)) %>%
hc_xAxis(type = "datetime") %>%
hc_plotOptions(area = list(stacking = "normal")) %>%
hc_legend(layout = "proximate", align = "right", labelFormatter = JS("function () {
ydat = this.yData;
return this.name + ' ' + ydat[ydat.length-1].toFixed(2);
}"))
hc
opts-export
we can then export the options into JSON directly via
the R object, or alternatively export the javascript
listviewer::jsonedit(
hc$x$hc_opts
)
# export JS options
usethis::use_directory("trash")
## ✓ Setting active project to '/Users/zg/r_projects/react.highcharts'
highcharter::export_hc(hc,filename = "trash/example-export.js")
jsx-mod
We modify our reactHC.jsx file to accept the options
renderValue: function (x) {
const options = x.options;
...
<HighchartsReact
highcharts={Highcharts}
options={options}/>
...
}
R-mod
& modify our R function to pass these options to
react & javascript
reactHC <- function(options = NULL, width = NULL, height = NULL, elementId = NULL) {
# forward options using x
x = list(
options = options
)
# create widget
htmlwidgets::createWidget(
name = 'reactHC',
x,
width = width,
height = height,
package = 'react.highcharts',
elementId = elementId
)
}
webpack-bundle
We then repeat the webpack (& R) bundle, document, install process
packer::bundle()
devtools::document()
devtools::install()
test-voila
Test & … Voila!
We now have a React & Highcharts htmlwidget that we can use in R,
Shiny, rmarkdown, quarto docs or anywhere you use R (or generally any of
the other 64 languages - I’m certain I’m short on the
count) that posit supports :) )
Open Q: I do wonder, is there a way for htmlwidgets
to interoperate with JS? Can a npm package use a
npmR package?
If you know, would you PM me?
react.highcharts::reactHC(
options = hc$x$hc_opts
)
While I plan to explore this further, that’s all for now!
The source code can be found Here
.jsoneditor.jsoneditor-mode-tree{
background: #ffffff;
}
$(function(){
$("#toc-highcharts-react-htmlwidgetimproving-it-a-bit > img").remove();
})