SlideShare a Scribd company logo
Confidential – do not duplicate or redistribute without permission from xtream srl
An introduction to reactive programming in Shiny
Milan, 13th September 2018
2 Contents
➢ What is reactive programming?
➢ Sources, conductors and endpoints
➢ Preventing reactivity: isolate
➢ observeEvent and eventReactive
1. Road to reactivity
What is reactive programming and why you should care about it
4
A one-way trip (1/3)
> x <- 1
> print(x)
[1] 1
> x <- 2
When the last statement is executed,
the value of x becomes 2, but the
printed value does not change
(obviously!)
5
A one-way trip (2/3)
> x <- 1
> y <- x + 1
> print(y)
[1] 2
> x <- 2
> print(y)
[1] 2
When the value of x changes, the value
of y does not, because the two
variables are not linked together
(obviously!)
6
A one-way trip (3/3)
print(x)
x x
x + 1
In the non-reactive realm, expressions
evaluate their input only when they
need, if an input changes after the
expression has been evaluated, the
result is not affected.
There are no push notifications!
7
The magic reactive world
# app.R
library(shiny)
ui <- fluidPage(
sidebarPanel(
sliderInput("n", label = "input", min = 0, max = 100, value = 50)
),
mainPanel(h1(textOutput("out")))
)
server <- function(input, output) {
output$out <- renderText(input$n)
}
shinyApp(ui = ui, server = server)
8 Up to here…
➢ Non-reactive expressions are lazy: they evaluate their input only when they are run
➢ This means that they cannot react to input changes
➢ Reactive expressions seems to go the other way round, reacting to input changes
➢ This is not how it actually works
9
➢ Reactivity is a feature added on top
of a language, it must follow the rule
of the language
➢ The only way to update the result of
an expression is re-running it
Everything is reactive
If you kindly ask
50Reactive
source
50Reactive
endpoint
10
➢ Reactivity is a feature added on top
of a language, it must follow the rule
of the language
➢ The only way to update the result of
an expression is re-running it
Everything is reactive
If you kindly ask
60
50
Reactive
source
Reactive
endpoint
11
➢ Reactivity is a feature added on top
of a language, it must follow the rule
of the language
➢ The only way to update the result of
an expression is re-running it
Everything is reactive
If you kindly ask
60
50 RE-RUN!
Reactive
source
Reactive
endpoint
12
➢ Reactivity is a feature added on top
of a language, it must follow the rule
of the language
➢ The only way to update the result of
an expression is re-running it
➢ This is what reactivity does. With
this approach, we don’t even need
to know what to re-run. Maybe.
Everything is reactive
If you kindly ask
60
60
Reactive
source
Reactive
endpoint
13
➢ We cannot re-run everything so fast
that the user does not even perceive
it
➢ We have to be smart
Lazyness
The right way
10Reactive
source
30
Reactive
endpoint
20
+
Reactive
conductor
14
➢ We cannot re-run everything so fast
that the user does not even perceive
it
➢ We have to be smart
Lazyness
The right way
10Reactive
source
30
Reactive
endpoint
40
+
Reactive
conductor
15
➢ We cannot re-run everything so fast
that the user does not even perceive
it
➢ We have to be smart
Lazyness
The right way
10Reactive
source
30
Reactive
endpoint
40
+
Reactive
conductor
16
➢ We cannot re-run everything so fast
that the user does not even perceive
it
➢ We have to be smart
Lazyness
The right way
10Reactive
source
30
Reactive
endpoint
40
+
Reactive
conductor
RE-RUN!
17
➢ We cannot re-run everything so fast
that the user does not even perceive
it
➢ We have to be smart
Lazyness
The right way
10Reactive
source
30
Reactive
endpoint
40
+
Reactive
conductor
RE-RUN!
RE-RUN!
18
➢ We cannot re-run everything so fast
that the user does not even perceive
it
➢ We have to be smart
➢ If we implement a proper cache-
invalidation system, we can only re-
run what needs to be. But how?
Lazyness
The right way
10Reactive
source
50
Reactive
endpoint
40
+
Reactive
conductor
19
➢ Reactive sources and conductor have a
dirty flag, meaning the cached results are
no longer valid
➢ Reactive sources and conductors know
which objects depend on them, and can
make them dirty, though an invalidation
event
➢ When an endpoint gets dirty, it is re-run.
➢ DANGER. If more endpoints get dirty at
the same time, there is no way of knowing
or imposing the execution order
Homing Pigeons
10Reactive
source
20
Reactive
endpoint
10
+
Reactive
conductor
20
➢ Reactive sources and conductor have a
dirty flag, meaning the cached results are
no longer valid
➢ Reactive sources and conductors know
which objects depend on them, and can
make them dirty, though an invalidation
event
➢ When an endpoint gets dirty, it is re-run.
➢ DANGER. If more endpoints get dirty at
the same time, there is no way of knowing
or imposing the execution order
Homing Pigeons
10Reactive
source
20
Reactive
endpoint
40
+
Reactive
conductor
DIRTY
21
➢ Reactive sources and conductor have a
dirty flag, meaning the cached results are
no longer valid
➢ Reactive sources and conductors know
which objects depend on them, and can
make them dirty, though an invalidation
event
➢ When an endpoint gets dirty, it is re-run.
➢ DANGER. If more endpoints get dirty at
the same time, there is no way of knowing
or imposing the execution order
Homing Pigeons
10Reactive
source
20
Reactive
endpoint
40
+
Reactive
conductor
DIRTY
INVALIDATE!
22
➢ Reactive sources and conductor have a
dirty flag, meaning the cached results are
no longer valid
➢ Reactive sources and conductors know
which objects depend on them, and can
make them dirty, though an invalidation
event
➢ When an endpoint gets dirty, it is re-run.
➢ DANGER. If more endpoints get dirty at
the same time, there is no way of knowing
or imposing the execution order
Homing Pigeons
10Reactive
source
20
Reactive
endpoint
40
+
Reactive
conductor
DIRTY
DIRTY
23
➢ Reactive sources and conductor have a
dirty flag, meaning the cached results are
no longer valid
➢ Reactive sources and conductors know
which objects depend on them, and can
make them dirty, though an invalidation
event
➢ When an endpoint gets dirty, it is re-run.
➢ DANGER. If more endpoints get dirty at
the same time, there is no way of knowing
or imposing the execution order
Homing Pigeons
10Reactive
source
20
Reactive
endpoint
40
+
Reactive
conductor
DIRTY
INVALIDATE!
24
➢ Reactive sources and conductor have a
dirty flag, meaning the cached results are
no longer valid
➢ Reactive sources and conductors know
which objects depend on them, and can
make them dirty, though an invalidation
event
➢ When an endpoint gets dirty, it is re-run.
➢ DANGER. If more endpoints get dirty at
the same time, there is no way of knowing
or imposing the execution order
Homing Pigeons
10Reactive
source
20
Reactive
endpoint
40
+
Reactive
conductor
DIRTY
RE-RUN!
25
➢ Reactive sources and conductor have a
dirty flag, meaning the cached results are
no longer valid
➢ Reactive sources and conductors know
which objects depend on them, and can
make them dirty, though an invalidation
event
➢ When an endpoint gets dirty, it is re-run.
➢ DANGER. If more endpoints get dirty at
the same time, there is no way of knowing
or imposing the execution order
Homing Pigeons
10Reactive
source
20
Reactive
endpoint
40
+
Reactive
conductor
DIRTY
RE-RUN!
26
➢ Reactive sources and conductor have a
dirty flag, meaning the cached results are
no longer valid
➢ Reactive sources and conductors know
which objects depend on them, and can
make them dirty, though an invalidation
event
➢ When an endpoint gets dirty, it is re-run.
➢ DANGER. If more endpoints get dirty at
the same time, there is no way of knowing
or imposing the execution order
Homing Pigeons
10Reactive
source
50
Reactive
endpoint
40
+
Reactive
conductor
27
➢ When a reactive expression parent
executes another one child, it leaves there
an homing pigeon, capable of reaching
the parent again
➢ When the child gets dirty, it frees the
homing pigeon
➢ When the homing pigeon gets to the
parent, it makes it dirty.
➢ This is why you cannot use a reactive
expression outside a reactive context.
Nobody leaves the pigeon.
Homing Pigeons
Why this title?
28 Up to here…
➢ Reactivity is nothing but a smart way of re-running expressions
➢ Results are cached, so that you don’t re-run something if you already have its result
➢ Reactivity uses messages: reactive expressions know which ones need their result
and can ask them to re-run them if their result changes
➢ We don’t need to go deeper in the implementation details
2. Shiny reactive flow
Sources, endpoints and conductors
30
➢ Instances of class reactivevalues
➢ Created by reactiveValues or
reactiveVal
➢ The default object input is a
collection of reactive sources
➢ When they change, they invalidate all
the objects which depend on them
Reactive sources
Reactive
source
31
➢ Created by render* or observe*
functions – e.g. renderText,
observeEvent, …
➢ The default object output is a
collection of reactive endpoints
➢ When invalidated, they re-run within a
negligible time.
➢ They do not return values, but they
perform actions – e.g. writing a log file,
updating the ui, …
Reactive endpoints
Reactive
endpoint
32
➢ Special functions created by the
*reactive functions (e.g.
reactive, eventReactive, …)
➢ Functions: they must return some
value. The result of the last
expression is returned by default
➢ When invalidated, they invalidate all
the conductors and the endpoints
which depend on them
Reactive conductors
Reactive
conductor
33
square = function(n) {
Sys.sleep(2)
n*n
}
output$computed = renderText(
square(input$n) + 1 / square(input$n)
)
Execution time?
~ 4s
square = reactive({
Sys.sleep(2)
input$n * input$n
})
output$computed = renderText(
square() + 1 / square()
)
Execution time?
~ 2s
Why using conductors?
34 Why using conductors?
➢ Caching results, thus improving performances
➢ Sharing intermediate results among different consumers
➢ Splitting long algorithms, thus improving readability and maintainability
3. Preventing reactivity
Isolate funciton and its usage
36
➢ A reactive endpoint depends on two
sources
➢ But you want the endpoint to be
recomputed only if one of them
changes
➢ Of course, you want that, when the
endpoint is re-run, it uses the most
updated value for both the sources
Preventing reactivity
10Reactive
source
30
Reactive
endpoint
20
isolate()
37
➢ A reactive endpoint depends on two
sources
➢ But you want the endpoint to be
recomputed only if one of them
changes
➢ Of course, you want that, when the
endpoint is re-run, it uses the most
updated value for both the sources
Preventing reactivity
10Reactive
source
30
Reactive
endpoint
40
isolate()
38
➢ A reactive endpoint depends on two
sources
➢ But you want the endpoint to be
recomputed only if one of them
changes
➢ Of course, you want that, when the
endpoint is re-run, it uses the most
updated value for both the sources
Preventing reactivity
20Reactive
source
30
Reactive
endpoint
40
isolate()
DIRTY
39
➢ A reactive endpoint depends on two
sources
➢ But you want the endpoint to be
recomputed only if one of them
changes
➢ Of course, you want that, when the
endpoint is re-run, it uses the most
updated value for both the sources
Preventing reactivity
20Reactive
source
30
Reactive
endpoint
40
INVALIDATE!
DIRTY
isolate()
40
➢ A reactive endpoint depends on two
sources
➢ But you want the endpoint to be
recomputed only if one of them
changes
➢ Of course, you want that, when the
endpoint is re-run, it uses the most
updated value for both the sources
Preventing reactivity
20Reactive
source
30
Reactive
endpoint
40
RE-RUN!
DIRTY
41
➢ A reactive endpoint depends on two
sources
➢ But you want the endpoint to be
recomputed only if one of them
changes
➢ Of course, you want that, when the
endpoint is re-run, it uses the most
updated value for both the sources
Preventing reactivity
20Reactive
source
60
Reactive
endpoint
40
isolate()
42
Assuming a couple of numeric inputs
n1 and n2 exists:
output$computed = renderText(
input$n1 + isolate(input$n2)
)
Preventing reactivity
The code
20Reactive
source
60
Reactive
endpoint
40
isolate()
4. Controlling reactivity
observeEvent and eventReactive: reactivity switches
44 Why controlling reactivity?
➢ You have a massive application, which let the user analyse data and tune some
parameter of a super-cool machine learning model
➢ Users can train the model against data, but this is a long, long procedure
➢ You don’t want model training to be triggered each time a user changes a
parameter, even if the model naturally depends on them
➢ So, you want to add a button to trigger the training algorithm, but you want training
to use the most updated values of parameters
45
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
numericInput("n", "Input:", value = 10),
actionButton('go', 'Go!')
),
mainPanel(
h1("Result"),
textOutput("computed")
)
)
)
server <- function(input, output) {
step2 = step1 = function(x){
Sys.sleep(1)
x+1
}
output$computed = renderText({
input$go
s1 = isolate(step1(input$n))
isolate(step2(s1))
})
}
shinyApp(ui = ui, server = server)
Controlling reactivity
A first attempt
goReactive
source
computed
Reactive
endpoint
n
isolate()
46
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
numericInput("n", "Input:", value = 10),
actionButton('go', 'Go!')
),
mainPanel(
h1("Result"),
textOutput("computed")
)
)
)
server <- function(input, output) {
step2 = step1 = function(x){
Sys.sleep(1)
x+1
}
output$computed = renderText({
input$go
s1 = isolate(step1(input$n))
isolate(step2(s1))
})
}
shinyApp(ui = ui, server = server)
➢ An actionButton returns a
number which is incremented by 1
each time it is pressed
➢ We take a reactive dependency
from go and we isolate all the rest
➢ This is not handy, nor readable. Why
should we use a reactive context if
we isolate all the inputs but one?
Controlling reactivity
A first attempt
47
server <- function(input, output) {
step2 = step1 = function(x){
Sys.sleep(1)
x+1
}
res = eventReactive(
input$go, {
s1 = step1(input$n)
step2(s1)
})
output$computed = renderText(
res()
)}
shinyApp(ui = ui, server = server)
Controlling reactivity
The right way
goReactive
source
computed
Reactive
endpoint
n
isolate()
res
48
➢ eventReactive has two main
arguments:
➢ A reactive expression to take
dependency on
➢ An expression to run when the first
argument gets invalidated
➢ It is a reactive conductor: it returns a
value
➢ Under the hood, it translate almost
exactly in the first example
➢ But this is more straightforward and
readable!
Controlling reactivity
The right way
server <- function(input, output) {
step2 = step1 = function(x){
Sys.sleep(1)
x+1
}
res = eventReactive(
input$go, {
s1 = step1(input$n)
step2(s1)
})
output$computed = renderText(
res()
)}
shinyApp(ui = ui, server = server)
49
server <- function(input, output) {
write_log_2 = write_log_1 =
function(x){
Sys.sleep(1)
print(x)
}
observeEvent(
input$go,
{
write_log_1(input$n)
write_log_2(input$n)
})
}
Controlling reactivity
The right way
goReactive
source
Reactive
endpoint
n
isolate()
50
➢ observeEvent has two main
arguments:
➢ A reactive expression to take
dependency on
➢ An expression to run when the
first argument gets invalidated
➢ It is not a reactive conductor, but a
reactive endpoint. It does not return
any value.
Controlling reactivity
The right way
server <- function(input, output) {
write_log_2 = write_log_1 =
function(x){
Sys.sleep(1)
print(x)
}
observeEvent(
input$go,
{
write_log_1(input$n)
write_log_2(input$n)
})
}
51
Use observeEvent whenever you want
to perform an action in response to an
event. Note that "recalculate a value"
does not generally count as performing
an action – see eventReactive for
that.
Use eventReactive to create a
calculated value that only updates in
response to an event.
This is just like a normal reactive
expression except it ignores all the
usual invalidations that come from its
reactive dependencies; it only
invalidates in response to the given
event.
observeEvent eventReactive
observeEvent vs
eventReactive
Source: https://shiny.rstudio.com/reference/shiny/1.0.0/observeEvent.html
52 Resources
The best place to start learning Shiny is the documentation home page:
https://shiny.rstudio.com/tutorial/
Here you can find lots of pointers to articles, videos and tutorials.
53 Contacts
Mail: info@xtreamers.io
Web: xtreamers.io
Twitter: @xtream_srl
Facebook: xtream
Linkedin: xtream-srl
Mail: emanuele.fabbiani@xtreamers.io
Github: @donlelef
Linkedin: emanuelefabbiani
xtream Emanuele Fabbiani

More Related Content

What's hot

Regular Grammar
Regular GrammarRegular Grammar
Regular Grammar
Ruchika Sinha
 
1.7 avl tree
1.7 avl tree 1.7 avl tree
1.7 avl tree
Krish_ver2
 
Transaction management DBMS
Transaction  management DBMSTransaction  management DBMS
Transaction management DBMS
Megha Patel
 
Database schema
Database schemaDatabase schema
Database schema
HerbertSemana1
 
Database systems
Database systemsDatabase systems
Database systems
NazmulHossen5
 
joins in database
 joins in database joins in database
joins in database
Sultan Arshad
 
10. Search Tree - Data Structures using C++ by Varsha Patil
10. Search Tree - Data Structures using C++ by Varsha Patil10. Search Tree - Data Structures using C++ by Varsha Patil
10. Search Tree - Data Structures using C++ by Varsha Patil
widespreadpromotion
 
Query processing and Query Optimization
Query processing and Query OptimizationQuery processing and Query Optimization
Query processing and Query Optimization
Niraj Gandha
 
Binary tree traversal ppt
Binary tree traversal pptBinary tree traversal ppt
Binary tree traversal ppt
PREEYANKAV
 
SQL Commands
SQL Commands SQL Commands
SQL Commands
Sachidananda M H
 
The Relational Data Model and Relational Database Constraints Ch5 (Navathe 4t...
The Relational Data Model and Relational Database Constraints Ch5 (Navathe 4t...The Relational Data Model and Relational Database Constraints Ch5 (Navathe 4t...
The Relational Data Model and Relational Database Constraints Ch5 (Navathe 4t...
Raj vardhan
 
Theory of dependencies in relational database
Theory of dependencies in relational databaseTheory of dependencies in relational database
Theory of dependencies in relational databaseJyoti Ranjan Pattnaik
 
The Relational Database Model
The Relational Database ModelThe Relational Database Model
The Relational Database Model
Shishir Aryal
 
Er diagram
Er diagramEr diagram
Er diagram
Sabana Maharjan
 
Formal Languages and Automata Theory unit 2
Formal Languages and Automata Theory unit 2Formal Languages and Automata Theory unit 2
Formal Languages and Automata Theory unit 2
Srimatre K
 
Normalization in DBMS
Normalization in DBMSNormalization in DBMS
Normalization in DBMS
Prateek Parimal
 
Joins in dbms and types
Joins in dbms and typesJoins in dbms and types
Joins in dbms and types
university of Gujrat, pakistan
 
Relational model
Relational modelRelational model
Relational model
Dabbal Singh Mahara
 
Oracle Database View
Oracle Database ViewOracle Database View
Oracle Database View
Eryk Budi Pratama
 

What's hot (20)

Regular Grammar
Regular GrammarRegular Grammar
Regular Grammar
 
1.7 avl tree
1.7 avl tree 1.7 avl tree
1.7 avl tree
 
Transaction management DBMS
Transaction  management DBMSTransaction  management DBMS
Transaction management DBMS
 
Database schema
Database schemaDatabase schema
Database schema
 
Database systems
Database systemsDatabase systems
Database systems
 
joins in database
 joins in database joins in database
joins in database
 
10. Search Tree - Data Structures using C++ by Varsha Patil
10. Search Tree - Data Structures using C++ by Varsha Patil10. Search Tree - Data Structures using C++ by Varsha Patil
10. Search Tree - Data Structures using C++ by Varsha Patil
 
Query processing and Query Optimization
Query processing and Query OptimizationQuery processing and Query Optimization
Query processing and Query Optimization
 
Binary tree traversal ppt
Binary tree traversal pptBinary tree traversal ppt
Binary tree traversal ppt
 
SQL Commands
SQL Commands SQL Commands
SQL Commands
 
The Relational Data Model and Relational Database Constraints Ch5 (Navathe 4t...
The Relational Data Model and Relational Database Constraints Ch5 (Navathe 4t...The Relational Data Model and Relational Database Constraints Ch5 (Navathe 4t...
The Relational Data Model and Relational Database Constraints Ch5 (Navathe 4t...
 
Joins And Its Types
Joins And Its TypesJoins And Its Types
Joins And Its Types
 
Theory of dependencies in relational database
Theory of dependencies in relational databaseTheory of dependencies in relational database
Theory of dependencies in relational database
 
The Relational Database Model
The Relational Database ModelThe Relational Database Model
The Relational Database Model
 
Er diagram
Er diagramEr diagram
Er diagram
 
Formal Languages and Automata Theory unit 2
Formal Languages and Automata Theory unit 2Formal Languages and Automata Theory unit 2
Formal Languages and Automata Theory unit 2
 
Normalization in DBMS
Normalization in DBMSNormalization in DBMS
Normalization in DBMS
 
Joins in dbms and types
Joins in dbms and typesJoins in dbms and types
Joins in dbms and types
 
Relational model
Relational modelRelational model
Relational model
 
Oracle Database View
Oracle Database ViewOracle Database View
Oracle Database View
 

Similar to Introduction to reactive programming with R and Shiny

JakartaOne Livestream CN4J: Bringing Reactive to Enterprise Developers
JakartaOne Livestream CN4J: Bringing Reactive to Enterprise DevelopersJakartaOne Livestream CN4J: Bringing Reactive to Enterprise Developers
JakartaOne Livestream CN4J: Bringing Reactive to Enterprise Developers
Jakarta_EE
 
Undefined Behaviour and Poison Values in LLVM
Undefined Behaviour and Poison Values in LLVMUndefined Behaviour and Poison Values in LLVM
Undefined Behaviour and Poison Values in LLVM
radcircles1059
 
TDC2016SP - Trilha Node.Js
TDC2016SP - Trilha Node.JsTDC2016SP - Trilha Node.Js
TDC2016SP - Trilha Node.Js
tdc-globalcode
 
The Rest of the Best
The Rest of the BestThe Rest of the Best
The Rest of the Best
Kevlin Henney
 
Reactive programming with scala and akka
Reactive programming with scala and akkaReactive programming with scala and akka
Reactive programming with scala and akka
Knoldus Inc.
 
Reactive Qt - Ivan Čukić (Qt World Summit 2015)
Reactive Qt - Ivan Čukić (Qt World Summit 2015)Reactive Qt - Ivan Čukić (Qt World Summit 2015)
Reactive Qt - Ivan Čukić (Qt World Summit 2015)
Ivan Čukić
 

Similar to Introduction to reactive programming with R and Shiny (6)

JakartaOne Livestream CN4J: Bringing Reactive to Enterprise Developers
JakartaOne Livestream CN4J: Bringing Reactive to Enterprise DevelopersJakartaOne Livestream CN4J: Bringing Reactive to Enterprise Developers
JakartaOne Livestream CN4J: Bringing Reactive to Enterprise Developers
 
Undefined Behaviour and Poison Values in LLVM
Undefined Behaviour and Poison Values in LLVMUndefined Behaviour and Poison Values in LLVM
Undefined Behaviour and Poison Values in LLVM
 
TDC2016SP - Trilha Node.Js
TDC2016SP - Trilha Node.JsTDC2016SP - Trilha Node.Js
TDC2016SP - Trilha Node.Js
 
The Rest of the Best
The Rest of the BestThe Rest of the Best
The Rest of the Best
 
Reactive programming with scala and akka
Reactive programming with scala and akkaReactive programming with scala and akka
Reactive programming with scala and akka
 
Reactive Qt - Ivan Čukić (Qt World Summit 2015)
Reactive Qt - Ivan Čukić (Qt World Summit 2015)Reactive Qt - Ivan Čukić (Qt World Summit 2015)
Reactive Qt - Ivan Čukić (Qt World Summit 2015)
 

Recently uploaded

Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, BetterWebinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
XfilesPro
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
Drona Infotech
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Łukasz Chruściel
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
Globus
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
rickgrimesss22
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
Shane Coughlan
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
Philip Schwarz
 
OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024
OpenMetadata
 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
Paco van Beckhoven
 
Game Development with Unity3D (Game Development lecture 3)
Game Development  with Unity3D (Game Development lecture 3)Game Development  with Unity3D (Game Development lecture 3)
Game Development with Unity3D (Game Development lecture 3)
abdulrafaychaudhry
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Globus
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
Safe Software
 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
Deuglo Infosystem Pvt Ltd
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
abdulrafaychaudhry
 
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
Google
 
Enterprise Software Development with No Code Solutions.pptx
Enterprise Software Development with No Code Solutions.pptxEnterprise Software Development with No Code Solutions.pptx
Enterprise Software Development with No Code Solutions.pptx
QuickwayInfoSystems3
 
Introduction to Pygame (Lecture 7 Python Game Development)
Introduction to Pygame (Lecture 7 Python Game Development)Introduction to Pygame (Lecture 7 Python Game Development)
Introduction to Pygame (Lecture 7 Python Game Development)
abdulrafaychaudhry
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Mind IT Systems
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
Boni García
 
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data AnalysisProviding Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Globus
 

Recently uploaded (20)

Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, BetterWebinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
 
OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024
 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
 
Game Development with Unity3D (Game Development lecture 3)
Game Development  with Unity3D (Game Development lecture 3)Game Development  with Unity3D (Game Development lecture 3)
Game Development with Unity3D (Game Development lecture 3)
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
 
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
 
Enterprise Software Development with No Code Solutions.pptx
Enterprise Software Development with No Code Solutions.pptxEnterprise Software Development with No Code Solutions.pptx
Enterprise Software Development with No Code Solutions.pptx
 
Introduction to Pygame (Lecture 7 Python Game Development)
Introduction to Pygame (Lecture 7 Python Game Development)Introduction to Pygame (Lecture 7 Python Game Development)
Introduction to Pygame (Lecture 7 Python Game Development)
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
 
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data AnalysisProviding Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
 

Introduction to reactive programming with R and Shiny

  • 1. Confidential – do not duplicate or redistribute without permission from xtream srl An introduction to reactive programming in Shiny Milan, 13th September 2018
  • 2. 2 Contents ➢ What is reactive programming? ➢ Sources, conductors and endpoints ➢ Preventing reactivity: isolate ➢ observeEvent and eventReactive
  • 3. 1. Road to reactivity What is reactive programming and why you should care about it
  • 4. 4 A one-way trip (1/3) > x <- 1 > print(x) [1] 1 > x <- 2 When the last statement is executed, the value of x becomes 2, but the printed value does not change (obviously!)
  • 5. 5 A one-way trip (2/3) > x <- 1 > y <- x + 1 > print(y) [1] 2 > x <- 2 > print(y) [1] 2 When the value of x changes, the value of y does not, because the two variables are not linked together (obviously!)
  • 6. 6 A one-way trip (3/3) print(x) x x x + 1 In the non-reactive realm, expressions evaluate their input only when they need, if an input changes after the expression has been evaluated, the result is not affected. There are no push notifications!
  • 7. 7 The magic reactive world # app.R library(shiny) ui <- fluidPage( sidebarPanel( sliderInput("n", label = "input", min = 0, max = 100, value = 50) ), mainPanel(h1(textOutput("out"))) ) server <- function(input, output) { output$out <- renderText(input$n) } shinyApp(ui = ui, server = server)
  • 8. 8 Up to here… ➢ Non-reactive expressions are lazy: they evaluate their input only when they are run ➢ This means that they cannot react to input changes ➢ Reactive expressions seems to go the other way round, reacting to input changes ➢ This is not how it actually works
  • 9. 9 ➢ Reactivity is a feature added on top of a language, it must follow the rule of the language ➢ The only way to update the result of an expression is re-running it Everything is reactive If you kindly ask 50Reactive source 50Reactive endpoint
  • 10. 10 ➢ Reactivity is a feature added on top of a language, it must follow the rule of the language ➢ The only way to update the result of an expression is re-running it Everything is reactive If you kindly ask 60 50 Reactive source Reactive endpoint
  • 11. 11 ➢ Reactivity is a feature added on top of a language, it must follow the rule of the language ➢ The only way to update the result of an expression is re-running it Everything is reactive If you kindly ask 60 50 RE-RUN! Reactive source Reactive endpoint
  • 12. 12 ➢ Reactivity is a feature added on top of a language, it must follow the rule of the language ➢ The only way to update the result of an expression is re-running it ➢ This is what reactivity does. With this approach, we don’t even need to know what to re-run. Maybe. Everything is reactive If you kindly ask 60 60 Reactive source Reactive endpoint
  • 13. 13 ➢ We cannot re-run everything so fast that the user does not even perceive it ➢ We have to be smart Lazyness The right way 10Reactive source 30 Reactive endpoint 20 + Reactive conductor
  • 14. 14 ➢ We cannot re-run everything so fast that the user does not even perceive it ➢ We have to be smart Lazyness The right way 10Reactive source 30 Reactive endpoint 40 + Reactive conductor
  • 15. 15 ➢ We cannot re-run everything so fast that the user does not even perceive it ➢ We have to be smart Lazyness The right way 10Reactive source 30 Reactive endpoint 40 + Reactive conductor
  • 16. 16 ➢ We cannot re-run everything so fast that the user does not even perceive it ➢ We have to be smart Lazyness The right way 10Reactive source 30 Reactive endpoint 40 + Reactive conductor RE-RUN!
  • 17. 17 ➢ We cannot re-run everything so fast that the user does not even perceive it ➢ We have to be smart Lazyness The right way 10Reactive source 30 Reactive endpoint 40 + Reactive conductor RE-RUN! RE-RUN!
  • 18. 18 ➢ We cannot re-run everything so fast that the user does not even perceive it ➢ We have to be smart ➢ If we implement a proper cache- invalidation system, we can only re- run what needs to be. But how? Lazyness The right way 10Reactive source 50 Reactive endpoint 40 + Reactive conductor
  • 19. 19 ➢ Reactive sources and conductor have a dirty flag, meaning the cached results are no longer valid ➢ Reactive sources and conductors know which objects depend on them, and can make them dirty, though an invalidation event ➢ When an endpoint gets dirty, it is re-run. ➢ DANGER. If more endpoints get dirty at the same time, there is no way of knowing or imposing the execution order Homing Pigeons 10Reactive source 20 Reactive endpoint 10 + Reactive conductor
  • 20. 20 ➢ Reactive sources and conductor have a dirty flag, meaning the cached results are no longer valid ➢ Reactive sources and conductors know which objects depend on them, and can make them dirty, though an invalidation event ➢ When an endpoint gets dirty, it is re-run. ➢ DANGER. If more endpoints get dirty at the same time, there is no way of knowing or imposing the execution order Homing Pigeons 10Reactive source 20 Reactive endpoint 40 + Reactive conductor DIRTY
  • 21. 21 ➢ Reactive sources and conductor have a dirty flag, meaning the cached results are no longer valid ➢ Reactive sources and conductors know which objects depend on them, and can make them dirty, though an invalidation event ➢ When an endpoint gets dirty, it is re-run. ➢ DANGER. If more endpoints get dirty at the same time, there is no way of knowing or imposing the execution order Homing Pigeons 10Reactive source 20 Reactive endpoint 40 + Reactive conductor DIRTY INVALIDATE!
  • 22. 22 ➢ Reactive sources and conductor have a dirty flag, meaning the cached results are no longer valid ➢ Reactive sources and conductors know which objects depend on them, and can make them dirty, though an invalidation event ➢ When an endpoint gets dirty, it is re-run. ➢ DANGER. If more endpoints get dirty at the same time, there is no way of knowing or imposing the execution order Homing Pigeons 10Reactive source 20 Reactive endpoint 40 + Reactive conductor DIRTY DIRTY
  • 23. 23 ➢ Reactive sources and conductor have a dirty flag, meaning the cached results are no longer valid ➢ Reactive sources and conductors know which objects depend on them, and can make them dirty, though an invalidation event ➢ When an endpoint gets dirty, it is re-run. ➢ DANGER. If more endpoints get dirty at the same time, there is no way of knowing or imposing the execution order Homing Pigeons 10Reactive source 20 Reactive endpoint 40 + Reactive conductor DIRTY INVALIDATE!
  • 24. 24 ➢ Reactive sources and conductor have a dirty flag, meaning the cached results are no longer valid ➢ Reactive sources and conductors know which objects depend on them, and can make them dirty, though an invalidation event ➢ When an endpoint gets dirty, it is re-run. ➢ DANGER. If more endpoints get dirty at the same time, there is no way of knowing or imposing the execution order Homing Pigeons 10Reactive source 20 Reactive endpoint 40 + Reactive conductor DIRTY RE-RUN!
  • 25. 25 ➢ Reactive sources and conductor have a dirty flag, meaning the cached results are no longer valid ➢ Reactive sources and conductors know which objects depend on them, and can make them dirty, though an invalidation event ➢ When an endpoint gets dirty, it is re-run. ➢ DANGER. If more endpoints get dirty at the same time, there is no way of knowing or imposing the execution order Homing Pigeons 10Reactive source 20 Reactive endpoint 40 + Reactive conductor DIRTY RE-RUN!
  • 26. 26 ➢ Reactive sources and conductor have a dirty flag, meaning the cached results are no longer valid ➢ Reactive sources and conductors know which objects depend on them, and can make them dirty, though an invalidation event ➢ When an endpoint gets dirty, it is re-run. ➢ DANGER. If more endpoints get dirty at the same time, there is no way of knowing or imposing the execution order Homing Pigeons 10Reactive source 50 Reactive endpoint 40 + Reactive conductor
  • 27. 27 ➢ When a reactive expression parent executes another one child, it leaves there an homing pigeon, capable of reaching the parent again ➢ When the child gets dirty, it frees the homing pigeon ➢ When the homing pigeon gets to the parent, it makes it dirty. ➢ This is why you cannot use a reactive expression outside a reactive context. Nobody leaves the pigeon. Homing Pigeons Why this title?
  • 28. 28 Up to here… ➢ Reactivity is nothing but a smart way of re-running expressions ➢ Results are cached, so that you don’t re-run something if you already have its result ➢ Reactivity uses messages: reactive expressions know which ones need their result and can ask them to re-run them if their result changes ➢ We don’t need to go deeper in the implementation details
  • 29. 2. Shiny reactive flow Sources, endpoints and conductors
  • 30. 30 ➢ Instances of class reactivevalues ➢ Created by reactiveValues or reactiveVal ➢ The default object input is a collection of reactive sources ➢ When they change, they invalidate all the objects which depend on them Reactive sources Reactive source
  • 31. 31 ➢ Created by render* or observe* functions – e.g. renderText, observeEvent, … ➢ The default object output is a collection of reactive endpoints ➢ When invalidated, they re-run within a negligible time. ➢ They do not return values, but they perform actions – e.g. writing a log file, updating the ui, … Reactive endpoints Reactive endpoint
  • 32. 32 ➢ Special functions created by the *reactive functions (e.g. reactive, eventReactive, …) ➢ Functions: they must return some value. The result of the last expression is returned by default ➢ When invalidated, they invalidate all the conductors and the endpoints which depend on them Reactive conductors Reactive conductor
  • 33. 33 square = function(n) { Sys.sleep(2) n*n } output$computed = renderText( square(input$n) + 1 / square(input$n) ) Execution time? ~ 4s square = reactive({ Sys.sleep(2) input$n * input$n }) output$computed = renderText( square() + 1 / square() ) Execution time? ~ 2s Why using conductors?
  • 34. 34 Why using conductors? ➢ Caching results, thus improving performances ➢ Sharing intermediate results among different consumers ➢ Splitting long algorithms, thus improving readability and maintainability
  • 35. 3. Preventing reactivity Isolate funciton and its usage
  • 36. 36 ➢ A reactive endpoint depends on two sources ➢ But you want the endpoint to be recomputed only if one of them changes ➢ Of course, you want that, when the endpoint is re-run, it uses the most updated value for both the sources Preventing reactivity 10Reactive source 30 Reactive endpoint 20 isolate()
  • 37. 37 ➢ A reactive endpoint depends on two sources ➢ But you want the endpoint to be recomputed only if one of them changes ➢ Of course, you want that, when the endpoint is re-run, it uses the most updated value for both the sources Preventing reactivity 10Reactive source 30 Reactive endpoint 40 isolate()
  • 38. 38 ➢ A reactive endpoint depends on two sources ➢ But you want the endpoint to be recomputed only if one of them changes ➢ Of course, you want that, when the endpoint is re-run, it uses the most updated value for both the sources Preventing reactivity 20Reactive source 30 Reactive endpoint 40 isolate() DIRTY
  • 39. 39 ➢ A reactive endpoint depends on two sources ➢ But you want the endpoint to be recomputed only if one of them changes ➢ Of course, you want that, when the endpoint is re-run, it uses the most updated value for both the sources Preventing reactivity 20Reactive source 30 Reactive endpoint 40 INVALIDATE! DIRTY isolate()
  • 40. 40 ➢ A reactive endpoint depends on two sources ➢ But you want the endpoint to be recomputed only if one of them changes ➢ Of course, you want that, when the endpoint is re-run, it uses the most updated value for both the sources Preventing reactivity 20Reactive source 30 Reactive endpoint 40 RE-RUN! DIRTY
  • 41. 41 ➢ A reactive endpoint depends on two sources ➢ But you want the endpoint to be recomputed only if one of them changes ➢ Of course, you want that, when the endpoint is re-run, it uses the most updated value for both the sources Preventing reactivity 20Reactive source 60 Reactive endpoint 40 isolate()
  • 42. 42 Assuming a couple of numeric inputs n1 and n2 exists: output$computed = renderText( input$n1 + isolate(input$n2) ) Preventing reactivity The code 20Reactive source 60 Reactive endpoint 40 isolate()
  • 43. 4. Controlling reactivity observeEvent and eventReactive: reactivity switches
  • 44. 44 Why controlling reactivity? ➢ You have a massive application, which let the user analyse data and tune some parameter of a super-cool machine learning model ➢ Users can train the model against data, but this is a long, long procedure ➢ You don’t want model training to be triggered each time a user changes a parameter, even if the model naturally depends on them ➢ So, you want to add a button to trigger the training algorithm, but you want training to use the most updated values of parameters
  • 45. 45 ui <- fluidPage( sidebarLayout( sidebarPanel( numericInput("n", "Input:", value = 10), actionButton('go', 'Go!') ), mainPanel( h1("Result"), textOutput("computed") ) ) ) server <- function(input, output) { step2 = step1 = function(x){ Sys.sleep(1) x+1 } output$computed = renderText({ input$go s1 = isolate(step1(input$n)) isolate(step2(s1)) }) } shinyApp(ui = ui, server = server) Controlling reactivity A first attempt goReactive source computed Reactive endpoint n isolate()
  • 46. 46 ui <- fluidPage( sidebarLayout( sidebarPanel( numericInput("n", "Input:", value = 10), actionButton('go', 'Go!') ), mainPanel( h1("Result"), textOutput("computed") ) ) ) server <- function(input, output) { step2 = step1 = function(x){ Sys.sleep(1) x+1 } output$computed = renderText({ input$go s1 = isolate(step1(input$n)) isolate(step2(s1)) }) } shinyApp(ui = ui, server = server) ➢ An actionButton returns a number which is incremented by 1 each time it is pressed ➢ We take a reactive dependency from go and we isolate all the rest ➢ This is not handy, nor readable. Why should we use a reactive context if we isolate all the inputs but one? Controlling reactivity A first attempt
  • 47. 47 server <- function(input, output) { step2 = step1 = function(x){ Sys.sleep(1) x+1 } res = eventReactive( input$go, { s1 = step1(input$n) step2(s1) }) output$computed = renderText( res() )} shinyApp(ui = ui, server = server) Controlling reactivity The right way goReactive source computed Reactive endpoint n isolate() res
  • 48. 48 ➢ eventReactive has two main arguments: ➢ A reactive expression to take dependency on ➢ An expression to run when the first argument gets invalidated ➢ It is a reactive conductor: it returns a value ➢ Under the hood, it translate almost exactly in the first example ➢ But this is more straightforward and readable! Controlling reactivity The right way server <- function(input, output) { step2 = step1 = function(x){ Sys.sleep(1) x+1 } res = eventReactive( input$go, { s1 = step1(input$n) step2(s1) }) output$computed = renderText( res() )} shinyApp(ui = ui, server = server)
  • 49. 49 server <- function(input, output) { write_log_2 = write_log_1 = function(x){ Sys.sleep(1) print(x) } observeEvent( input$go, { write_log_1(input$n) write_log_2(input$n) }) } Controlling reactivity The right way goReactive source Reactive endpoint n isolate()
  • 50. 50 ➢ observeEvent has two main arguments: ➢ A reactive expression to take dependency on ➢ An expression to run when the first argument gets invalidated ➢ It is not a reactive conductor, but a reactive endpoint. It does not return any value. Controlling reactivity The right way server <- function(input, output) { write_log_2 = write_log_1 = function(x){ Sys.sleep(1) print(x) } observeEvent( input$go, { write_log_1(input$n) write_log_2(input$n) }) }
  • 51. 51 Use observeEvent whenever you want to perform an action in response to an event. Note that "recalculate a value" does not generally count as performing an action – see eventReactive for that. Use eventReactive to create a calculated value that only updates in response to an event. This is just like a normal reactive expression except it ignores all the usual invalidations that come from its reactive dependencies; it only invalidates in response to the given event. observeEvent eventReactive observeEvent vs eventReactive Source: https://shiny.rstudio.com/reference/shiny/1.0.0/observeEvent.html
  • 52. 52 Resources The best place to start learning Shiny is the documentation home page: https://shiny.rstudio.com/tutorial/ Here you can find lots of pointers to articles, videos and tutorials.
  • 53. 53 Contacts Mail: info@xtreamers.io Web: xtreamers.io Twitter: @xtream_srl Facebook: xtream Linkedin: xtream-srl Mail: emanuele.fabbiani@xtreamers.io Github: @donlelef Linkedin: emanuelefabbiani xtream Emanuele Fabbiani