The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.
This tutorial demonstrates how to build a dynamic Shiny application
using reactRouter
for routing and shiny.fluent
for modern UI components, all within the rhino
framework.
We’ll use Dota 2 API data as an
example of routing multiple pages.
Initially, ensure you have the necessary rhino package installed. You can do this by running the following command in your R console:
Next, you will need to create a new rhino project. If you haven’t already set up a rhino project, you can do so by running the following command in your R console:
This will create a basic structure for your application. Add the
following libraries to your dependencies.R
file:
# dependencies.R
library(rhino) # App structure
library(httr) # API requests
library(shiny.fluent) # UI components
library(reactRouter) # Client-side routing
library(echarts4r) # Charting
library(stringdist) # String matching
library(treesitter) # Optional: Syntax parsing
library(treesitter.r) # Optional: R syntax support
and then
Now we are ready to go.
In this example, we will create a simple application that displays information about Dota 2 heroes. The application will have multiple routes, allowing users to navigate between different pages.
The components of the application will be structured as follows:
The final strucutre of the app
will look like this:
├── app
│ ├── js
│ │ └── index.js
│ ├── logic
│ │ ├── data.R
│ │ └── utils.R
│ ├── main.R
│ ├── static
│ │ ├── css
│ │ │ └── app.min.css
│ │ ├── favicon.ico
│ │ └── js
│ │ └── app.min.js
│ ├── styles
│ │ └── main.scss
│ └── view
│ ├── benchmark.R
│ ├── details.R
│ ├── header.R
│ ├── home.R
│ ├── menu.R
│ └── rank.R
├── app.R
├── config.yml
├── dependencies.R
├── renv.lock
├── rhino.yml
└── run_dev.R
The main part of the application to address the routing and the UI
components is in the app.R
file.
# app / main.R
box::use(
app / view / home,
app / view / menu,
app / view / details,
app / view / benchmark,
app / view / rank
)
# Define UI with namespaced modules
ui <- function(id) {
ns <- shiny::NS(id) # Namespace for module isolation
shiny.fluent::fluentPage(
reactRouter::HashRouter(
reactRouter::Routes(
# Home page route
reactRouter::Route(path = "/", element = home$ui(ns("home"))),
# Project-based nested routes
reactRouter::Route(
path = "/:projectId/*",
element = menu$ui(ns("menu")), # Common layout/menu
children = list(
reactRouter::Route(
path = "details",
element = details$ui(ns("details"))
),
reactRouter::Route(
path = "benchmark",
element = benchmark$ui(ns("benchmark"))
),
reactRouter::Route(
path = "rank",
element = rank$ui(ns("rank"))
)
)
),
# Fallback for undefined routes
reactRouter::Route(path = "*", element = "Custom error 404")
)
)
)
}
#' @export
server <- function(id) {
shiny::moduleServer(id, function(input, output, session) {
hero_selected <- home$server("home")
shiny::observe({
shiny::req(hero_selected())
print(paste0("hero_id selected: ", hero_selected()))
})
menu$server("menu", hero_selected = hero_selected)
details$server("details", hero_selected = hero_selected)
benchmark$server("benchmark", hero_selected = hero_selected)
rank$server("rank", hero_selected = hero_selected)
})
}
This function defines the overall layout and routing of the application using reactRouter. It contains four key parts:
Top-level routing via HashRouter()
and
Routes()
.
Root Route /: Displays the home page.
Nested Route /:projectId/*:
Displays a layout (menu) and child routes (details, benchmark, rank).
Each sub-route renders a different module UI (e.g., details\(ui, benchmark\)ui).
Fallback * Route: Catches any undefined paths and shows a custom 404 message.
You can now run your app locally with the following script:
In this tutorial, dynamic Shiny application using:
rhino
for structured project
setup.shiny.fluent
for modern and
interactive UI.reactRouter
for dynamic and nested
client-side routing.This setup provides flexibility, scalability, and maintainability for more complex Shiny applications.
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.