Import of jsx files
HorseBinky opened this issue · 6 comments
Hi!
I'm new to the colourful world of shiny.
I have some experience with React and try now to import an JSX file into the main shiny UI and then render it into the document by
tags$head(
tags$script(HTML( babel_transform('ReactDOM.render(
<div><App/></div>, document.getElementById("app"))') ),
html_dependency_react()
)
),
`
But the react component is not recognized. I would be very thankful for any hint or an example!
Thanks!
Stefan
Glad you are trying it out, since React and Vue components can offer a lot of very nice functionality within a Shiny app. I still have not settled on the best workflow, so would love your thoughts as you work through this. Will you let me know if this helps? Also not sure if you saw https://www.jsinr.me/2017/11/19/react-in-r/ but that might help as well. I plan to continue the series soon.
library(shiny)
library(reactR)
library(htmltools)
ui <- tagList(
# ReactDOM now requires symbol and Set, so will need a polyfill
# to work in RStudio Viewer
# and I plan to add this to reactR as a dependency helper
# since the js needs to be a local file to work
# see https://github.com/g2inR/g2r/blob/master/R/dependencies.R#L45-L54
# open in Chrome or other modern browser to see it working
html_dependency_react(),
tags$div(id = "app"),
tags$script(HTML(
babel_transform(
"
var div = <div>Hi I'm working. Now what ? :)</div>
ReactDOM.render(
div,
document.getElementById('app')
)
"
)
))
)
server <- function(input, output, session) {}
shinyApp(ui, server)
Thank's for the fast response!
Your example works quite nice. But I'm still struggling with the import of separate React files and integrate them in the shiny infrastructure.
I.e. I have the following react app:
export default class App extends React.Component {
render(){
return(
<div>
Pony 4 life for {this.props.name}
</div>
)
}
}
How do I import it into shiny and render it into the DOM.
In JS I would import it like:
import App from 'app'
In the shiny UI then the component has to be rendered into the DOM like:
tags$script(HTML(
babel_transform(
"ReactDom.render(
<App name="Mr. Smith" />, document.getElementById('app')
)"
)))
Thanks for your help!
Cheers,
Stefan
You can do this, but I'm betting you are thinking (like me) this is still too hard. So, remove the export default
before you declare the class
.
library(shiny)
library(reactR)
library(htmltools)
ui <- tagList(
# ReactDOM now requires symbol and Set, so will need a polyfill
# to work in RStudio Viewer
# and I plan to add this to reactR as a dependency helper
# since the js needs to be a local file to work
# see https://github.com/g2inR/g2r/blob/master/R/dependencies.R#L45-L54
# open in Chrome or other modern browser to see it working
html_dependency_react(),
tags$div(id = "app"),
tags$div(id = "app2"),
tags$script(HTML(
babel_transform(
"
class App extends React.Component {
render(){
return(
<div>
Pony 4 life for {this.props.name}
</div>
)
}
}
ReactDOM.render(
<App name='Mr. Smith' />, document.getElementById('app')
)
ReactDOM.render(
<App name='Mrs. Roberts' />, document.getElementById('app2')
)
"
)
))
)
server <- function(input, output, session) {}
shinyApp(ui, server)
Once you have defined the App
in tags$script
once, then you can reuse throughout the page. This example might help https://github.com/timelyportfolio/reactR/blob/master/inst/examples/office-fabric.R as you try to convert examples from the web into R.
All right after some testing I'm one step further.
library(shiny)
library(reactR)
library(htmltools)
ui <- tagList(
# ReactDOM now requires symbol and Set, so will need a polyfill
# to work in RStudio Viewer
# and I plan to add this to reactR as a dependency helper
# since the js needs to be a local file to work
# see https://github.com/g2inR/g2r/blob/master/R/dependencies.R#L45-L54
# open in Chrome or other modern browser to see it working
html_dependency_react(),
tags$div(id = "app"),
tags$script(HTML(
babel_transform(paste0(readLines("www/app.js"),collapse='\n')
))
)
server <- function(input, output, session) {}
shinyApp(ui, server)
further.
The app.js looks like this. So the rendering is done by the app.js.
class App extends React.Component {
render(){
return(
<div>
Pony 4 life for {this.props.name}
</div>
)
}
}
ReactDOM.render(
<App name='Mr. Smith' />, document.getElementById('app')
)
In the next step I want to extend the App component by importing a separate react component from another file.
import Cat from './cat.js'
class App extends React.Component {
render(){
return(
<div>
Pony 4 life for {this.props.name}
< Cat sleepy='very much' />
</div>
)
}
}
At the moment I run into the "ReferenceError: require is not defined" error because require is not standard by JS.
@HorseBinky, so without the JavaScript build tools, we lose import
, export
, require
, etc. You'll need to add the ./cat.js
inline for it to be available. Hope this makes sense.
going to close...feel free to reopen. Enjoyed working through this and still hope to make this easier.