I am trying to decompose the code of my shiny app in order to improve readability and to test some functions using the testthat
package.
I would like to have some files (for example server_utils.R
) in which I can write "normal" functions that I can test and then make them reactive.
For example I would like to have something like this in server_utils.R
:
my_sum <- function(x, y) {
x + y
}
and something like this in the app:
my_sum_reactive(input$x, input$y)
Do you know if a such behavior is possible?
A reactive expression is an R expression that uses widget input and returns a value. The reactive expression will update this value whenever the original widget changes. To create a reactive expression use the reactive function, which takes an R expression surrounded by braces (just like the render* functions).
Reactivity is how Shiny determines which code in server() gets to run when. Some types of objects, such as the input object or objects made by reactiveValues() , can trigger some types of functions to run whenever they change.
shinyApp. Finally, we use the shinyApp function to create a Shiny app object from the UI/server pair that we defined above. We save all of this code, the ui object, the server function, and the call to the shinyApp function, in an R script called app. R .
Shiny modules is what might help you.
See here: https://shiny.rstudio.com/articles/modules.html
As you can read in the article the desired functionality to pass in input is possible if you wrap the input in a reactive()
function. (See the end of the "Writing server functions" section of the article).
You would define the my_sum
function as follows:
(Note that you have to use the variables a
and b
as reactives a()
and b()
and wrap the result in a reactive()
function.)
my_sum <- function(input, output, session, a, b) {
reactive(as.numeric(a()) + as.numeric(b()))
}
And could use it as:
my_sum_reactive <- callModule(my_sum, "id", reactive(input$a), reactive(input$b))
which is then usable as:
my_sum_reactive()
Reproducible example:
library(shiny)
my_sum <- function(input, output, session, a, b) {
reactive(as.numeric(a()) + as.numeric(b()))
}
ui <- fluidPage({
fluidRow(
selectInput("a", "a", 1:3),
selectInput("b", "b", 1:3),
textOutput("txt")
)
})
server <- function(input, output, session) {
my_sum_reactive <- callModule(my_sum, "id", reactive(input$a), reactive(input$b))
output$txt <- renderText(paste0("The sum is: ", my_sum_reactive()))
}
shinyApp(ui, server)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With