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.