# install.packages('pak')
::pak('mjfrigaard/shinypak')
paklibrary(shinypak)
Debug
Expand the callout boxes below to review what we’ve covered in the last five chapters:
Debugging is the process of identifying, analyzing, and fixing errors in our code.1 In Shiny apps, debugging can be challenging because the reactive model involves dynamic interactions and a non-linear flow of execution between inputs, reactive expressions, and outputs. Consider the diagram below that illustrates the reactive flow for the scatter plot graph in our application:
The inputs are collected by the variable input module2 (as var_inputs()
) and passed to the scatter display module3, where they become the inputs()
for our graph utility function.4
Our application launches with pre-selected values for the x
, y
and color
graph inputs, along with values for the size and opacity (alpha) of the points. Users can change the graph inputs or add a title, but by having pre-selected values, we guarantee the graph renders when the application launches.
%%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': 'monospace'}}}%% flowchart TD subgraph Inputs["Inputs"] VarInput[Variables/aesthetics] TitleInput["'new plot title'"] end subgraph React["Reactives"] R1["<code>var_inputs()</code> "] R2["<code>inputs()</code>"] R3["Updates <code>var_inputs</code>"] R4["Adds title with <code>labs()</code>"] end subgraph Output["Output"] O1[Graph] end VarInput --> R1 TitleInput <--> R3 R1 --> R2 R2 <--> R4 R3 <--> R2 R2 --> O1 R4 <--> O1 style Inputs fill:#FFFFFF,stroke:#333,stroke-width:1px,rx:5,ry:5 style React fill:#FFFFFF,stroke:#333,stroke-width:1px,rx:5,ry:5 style Output fill:#FFFFFF,stroke:#333,stroke-width:1px,rx:5,ry:5 style VarInput fill:#4CBB9D style TitleInput fill:#4CB7DB style R1 fill:#4CBB9D style R2 fill:#4CBB9D style R3 fill:#4CB7DB style R4 fill:#4CB7DB style O1 fill:#4CBB9D
Updating the plot title
Shiny is inherently asynchronous, so bugs can originate from reactive dependencies, execution order, utility functions, hidden states, lazy evaluation, and invalidation (i.e., reactive()
, observe()
, isolate()
, etc.).
For example, we could have an incorrectly defined inputId
s or outputId
s in the UI, which causes our graph utility function to fail. We could also have missing parentheses on reactive values in the server. Finally, the bug could be originating from the output/render point.
%%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': 'monospace'}}}%% flowchart TD subgraph Inputs["Inputs"] VarInput[Variables/aesthetics] TitleInput["'new plot title'"] end subgraph React["Reactives"] R1["<code>var_inputs()</code>"] R2["<code>inputs()</code>"] R3["Updates <code>var_inputs</code>"] R4["Adds title with <code>labs()</code>"] B1["🪲<code>inputId()</code> or <code>outputId()</code>🪲"] B2["🪲<code>scatter_plot()</code> function🪲"] B3["🪲<code>observe()</code> listener🪲"] B3["🪲<code>observe()</code> listener🪲"] B4["🪲Parentheses <code>()</code> listener🪲"] end subgraph Output["Output"] O1[Graph] B5["🪲<code>render_*</code> functions🪲"] end VarInput --> R1 Inputs --> B1 --> R1 Inputs --> B1 --> R3 TitleInput <--> R3 R1 --> R2 R2 --> B2 B2 --> R4 R3 --> B3 B3 --> R2 R2 --> B2 B2 --> O1 R4 --> B4 B2 --> B5 B5 --> O1 style Inputs fill:#FFFFFF,stroke:#333,stroke-width:1px,rx:5,ry:5 style React fill:#FFFFFF,stroke:#333,stroke-width:1px,rx:5,ry:5 style Output fill:#FFFFFF,stroke:#333,stroke-width:1px,rx:5,ry:5 style VarInput fill:#4CBB9D style TitleInput fill:#4CB7DB style B1 fill:#FFFFFF,color:#931314,stroke:#931314,stroke-width:3px,rx:10,ry:10 style B2 fill:#FFFFFF,color:#931314,stroke:#931314,stroke-width:3px,rx:10,ry:10 style B3 fill:#FFFFFF,color:#931314,stroke:#931314,stroke-width:3px,rx:10,ry:10 style B4 fill:#FFFFFF,color:#931314,stroke:#931314,stroke-width:3px,rx:10,ry:10 style B5 fill:#FFFFFF,color:#931314,stroke:#931314,stroke-width:3px,rx:10,ry:10 style R1 fill:#4CBB9D style R2 fill:#4CBB9D style R3 fill:#4CB7DB style R4 fill:#4CB7DB style O1 fill:#4CBB9D
Possible locations of bugs in a reactive model
Understanding the interplay of reactivity, lazy evaluation, asynchronous execution, and hidden states will help us diagnose and resolve bugs in our Shiny app-packages. We have to employ specific strategies and tools to handle Shiny bugs effectively, and some of the traditional debugging approaches can fall short in reactive contexts. The chapters in this section will cover how to adapt common methods for debugging R code to use with our Shiny application.
The definition in this article from AWS gives a great general overview of debugging.↩︎
Our variable input model is in
R/mod_var_input.R
.↩︎The graph display module is in
R/mod_scatter_display.R
.↩︎The graph utility function is in
R/scatter_plot.R
↩︎