-
Couldn't load subscription status.
- Fork 37
HTMLWidget and Shiny input integration helpers #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@alandipert playing with the pull, and I picked the magical
I'd love to hear your thoughts and please feel free to tell me if this is expanding beyond expected scope. Thanks! |
|
@timelyportfolio very cool experiment!
None of this feels out of scope to me, I'm very grateful for your experience report! You've hit on some really important/interesting things. |
|
@alandipert regarding html elements such as div we have a clue in that React.createElement expects a string ‘div’ rather than an unquoted component. Sorry that I won’t be on computer until tonight but could we simply double quote html elements or if not upper case and not found in components then infer that it is an html element. I don’t think we need to whitelist because I believe React.dom handles this. |
|
@timelyportfolio Ah yes, good point about React checking validity for us 👍 |
|
@alandipert I just remembered this ancient idea rstudio/htmltools#72 of using |
|
@timelyportfolio awesome, yes I thought of a similar scheme in the shower today! I was thinking something like a function, I think we can possibly do a couple extra cool things:
I'm aware of another related thing, |
|
@timelyportfolio I took a stab at output$spring <- renderSpringwidget(
springwidget(
data = NULL,
spring(
from = list(opacity = 0),
to = list(opacity = 1),
reactR::evalJS("props => <h1 style={props}>hello</h1>")
)
)
)The |
|
@alandipert the loop on the react-spring site is the result of an additional rewind component that is not part of react-spring. The effect should only happen once as you describe. I played around yesterday on npm download charts and was surprised to see recharts as the top download. Traveling today and tomorrow so won’t be able to do much but will get back on it once settled. Guessing there might be security concerns with eval but that is an area I know little about. Might want to check with some RStudio folks on the security aspect. |
|
@timelyportfolio after consulting with @jcheng5 we decided to hold off on Thanks for the pointer to recharts -- it looks very amenable to our approach, I'll play with it too. Safe travels, looking forward to collaborating with you further when you're back. |
|
@alandilpert ok, understood. I think we should discuss this in the Readme or documentation, so users also understand the decision and also the potential for addressing later. I'll pivot my example use cases to those that don't require this functionality. |
|
@alandipert @jcheng5 I started another widget roffice as an alternate example. As part of the testing, I built a proof of concept for adding Shiny event integration in Here is how this integration would look. A user would add a |
|
@timelyportfolio that's an interesting approach. I like it! Compared to We haven't discussed beyond the |
|
@timelyportfolio I had one thought, that perhaps |
|
@alandipert shinyEvent probably is a bit more descriptive. Just thought it would be a safe means of accomplishing communication especially considering very short timeline. If acceptable, how would you like to incorporate? Pull request to your enhancements branch? One other question is how to best id the event. In addition to shinyEvent we could also consider shinyId as another prop that when undefined could stick with current behavior. Or a user could specify id attribute that we could use. |
|
@timelyportfolio Feel free to make a commit to the I'm in favor of incorporating this ASAP barring an objection by @jcheng5. I think it gives us a very nice "get values back to R" story and is a simple thing to document and maintain. Thanks for coming up with it! |
R/reacttools.R
Outdated
| reactMarkup <- function(tag) { | ||
| stopifnot(class(tag) == "shiny.tag" | ||
| || (is.character(tag) && length(tag) == 1)) | ||
| list(tag = tag, class = "reactR.markup") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inherits(tag, "shiny.tag") seems more appropriate here. Also, what about "shiny.tag.list"? Perhaps you could allow a lit then wrap it in a div?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great point about tag lists. There's actually an analogous React thing we could support that they could turn into, React.Fragment. But I think we should maybe add that in a future PR.
| stop("Component name must be specified and start with an upper case character") | ||
| } | ||
| htmltools::tag(name, varArgs) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might want to add a class or a subclass here? As a package author, I might want to know if a user is supplying a component versus a tag
…rn how to create a binding
Changes to htmlwidgets vignette

Rationale
reactR is a great effort to close the gap between the React and R ecosystems and proposes a way to use JSX without installing any JavaScript build tools, which greatly empowers a certain category of users.
However, another category of "power" users — those who wish to consume JavaScript libraries from npm, or write their own components with the assistance of JavaScript tools and libraries — are not as well supported.
In lieu of tooling and documentation in reactR for this user category, each developer must create their own patterns for interfacing Shiny and React. They must also select and configure their JavaScript build tools manually.
The lower we make the bar for writing new widgets and inputs based on React, the more widget and input authors we can create. The more authors, the more widgets and inputs. The more widgets, the more empowered the larger R community of widget and input consumers becomes.
Objectives
reactR::component: Analogous tohtmltools::tagreactR::React: Analogous tohtmltools::tagsreactR.hydrate: Recursively converts a JSON-encoded React component tree as generated on the R side into a Reactive element. Used directly by Shiny inputs and outputs.reactR.reactWidget: Accepts a set of React components to make accessible within the context of an HTMLWidget, usinghydrateinternally to render components.Tasks
sparklineswidget_html.Complete and fully document the react-color Shiny input exampleDeferredWrite a React-based Shiny input scaffold functionDeferredOpen Questions
React$SomeComponent(x = 1)orcomponent("SomeComponent", x = 1)?Reactin the style ofhtmltools::tags, but Winston suggested a function likecomponent, with the argument that HTML tags are closed but React component names are open. So, it's not like they can be auto-completed. I personally lean toward a function, but maybe we should just have both? (similar to htmltools::tag + htmltools::tags)reactR::componentinreacttools.Rtake avarArgslist just likehtmltools::tag?--watch