With shiny.fluent we strived to build an interface for Microsoft’s Fluent UI which would be straightforward and natural to use in Shiny. However React, the underlying JavaScript technology, works in a vastly different manner, so the abstractions aren’t perfect. Here are a few things you need to know in order to effectively work with shiny.fluent.
Fluent inputs
Shiny has a notion of “inputs”, which does not exist in React. Still, you can connect React components to Shiny using appropriate arguments - in particular event handlers and default values. For example, you can use Checkbox
in the following way:
shinyApp(
ui = tagList(
Checkbox(onChange = setInput("checkbox", 2), defaultChecked = TRUE, label = "Checkbox"),
textOutput("value")
),
server = function(input, output) {
output$value <- renderText(deparse(input$checkbox))
}
)
With setInput("checkbox", 2)
we create a JavaScript function which takes its second argument and sends it to Shiny as input$checkbox
. The same effect could be achieved with JS("(e, value) => Shiny.setInputValue('checkbox', value)")
.
The React interface is powerful, but somewhat inconvenient. To make it easier to use components as Shiny inputs, we provide wrappers with .shinyInput
suffix. They provide an interface analogous to vanilla Shiny inputs: inputId
and optional value
. The checkbox usage above can be translated to:
Checkbox.shinyInput("checkbox", value = TRUE, label = "Checkbox")
Additionally, the wrapper:
- can be updated using
updateCheckbox.shinyInput()
, - sends its initial value to Shiny when it is first rendered.
Dynamic rendering
When you need to dynamically render UI, most of the time you can just go with uiOutput
and renderUI
. However in some cases you might want to use the analogous ?reactOutput
and ?renderReact
, which preserve the state of components on rerenders. To understand what that means, consider the following example:
shinyApp(
ui = div(
Checkbox.shinyInput("disabled", label = "Disable"),
reactOutput("ui")
),
server = function(input, output) {
output$ui <- renderReact({
TextField.shinyInput("text", label = "TextField", disabled = input$disabled)
})
}
)
This app displays a checkbox and a text field. The text field is rendered dynamically, and whether it is enabled or not depends on the value of the checkbox.
If we input some text into the text field and toggle the checkbox, the text field will become disabled, but its contents will be preserved. If we replaced reactOutput
and renderReact
with uiOutput
and renderUI
, the contents would be cleared each time we toggled the checkbox.