You can add URL pages in Quarto document or R shiny like so:
library(reactRouter)
HashRouter(
NavLink(to = "/", "Main"),
NavLink(to = "/analysis", "Analysis"),
Routes(
Route(path = "/", element = "Main content"),
Route(path = "/analysis", element = "Analysis content")
)
)
A minimal example using shiny.
library(shiny)
library(reactRouter)
ui <- HashRouter(
NavLink(to = "/", "Main"),
shiny::br(),
NavLink(to = "/other", "Other"),
Routes(
Route(
path = "/",
element = uiOutput(outputId = "uiMain")
),
Route(
path = "/other",
element = uiOutput(outputId = "uiOther")
)
)
)
server <- function(input, output, session) {
output$uiMain <- renderUI( { p("Content home") } )
output$uiOther <- renderUI( { p("Other content") })
}
shinyApp(ui = ui, server = server)
A minimal example using bslib.
library(reactRouter)
library(bslib)
library(htmltools)
reactRouter::HashRouter(
bslib::page_navbar(
title = "reactRouter with bslib",
nav_item(
reactRouter::NavLink(
"Home",
to = "/"
)
),
nav_item(
reactRouter::NavLink(
"Analysis",
to = "/analysis"
)
),
reactRouter::Routes(
reactRouter::Route(
path = "/",
element = div(
tags$h3("Home page"),
p("A basic example of reactRouter with bslib.")
)
),
reactRouter::Route(
path = "/analysis",
element = "Content analysis"
),
reactRouter::Route(path = "*", element = "Custom error 404")
)
)
)
A minimal example using shinyMaterialUI.
# remotes::install_github("lgnbhl/shinyMaterialUI")
library(shinyMaterialUI)
HashRouter(
Box(
sx = list(flexGrow = 1),
AppBar(
position = "static",
Toolbar(
Typography(
variant = "h6",
component = "div",
sx = list(mr = 1),
"shinyMaterialUI"
),
NavLink(
to = "/",
Button(
color = "inherit",
"Home"
)
),
NavLink(
to = "analysis",
Button(
color = "inherit",
"Analysis"
)
)
)
),
Box(
reactRouter::Routes(
reactRouter::Route(
path = "/",
element = Box("Home page", sx = list(p = 1))
),
reactRouter::Route(
path = "/analysis",
element = Box("Content analysis", sx = list(p = 1))
),
reactRouter::Route(path = "*", element = "Error 404")
)
)
)
)
Find more examples with shinyMaterialUI here.
# adapted from example of shiny.router
# https://github.com/Appsilon/shiny.router/tree/main/examples/shiny_modules
library(shiny)
library(reactRouter)
# This creates UI for each page.
page <- function(title, content, id) {
ns <- NS(id)
div(
titlePanel(title),
p(content),
textOutput(ns("click_me"))
)
}
# Both sample pages.
root_page <- page("Home page", "Home page clicks", "root")
second_page <- page("Other page", "Other page clicks", "second")
server_module <- function(id, clicks, power = 1) {
moduleServer(id, function(input, output, session) {
output$click_me <- renderText({
as.numeric(clicks())^power
})
})
}
# Create output for our router in main UI of Shiny app.
ui <- reactRouter::HashRouter(
NavLink(to = "/", "Main"), br(),
NavLink(to = "/other", "Other"),
actionButton("clicks", "Click me!"),
Routes(
Route(
path = "/",
element = div(
root_page
)
),
Route(
path = "/other",
element = div(
second_page
)
)
)
)
# Plug router into Shiny server.
server <- function(input, output, session) {
clicks <- reactive({
input$clicks
})
server_module("root", clicks = clicks, power = 1)
server_module("second", clicks = clicks, power = 2)
}
# Run server in a standard way.
shinyApp(ui, server)
As React Router provides client routing, you can easily create multiple routes in a Quarto or R markdown documents:
# code to run in a Quarto document
# example adapted from: https://github.com/remix-run/react-router/tree/dev/examples/basic
library(reactRouter)
library(htmltools)
Layout <- div(
# A "layout route" is a good place to put markup you want to
# share across all the pages on your site, like navigation.
tags$nav(
tags$ul(
tags$li(
reactRouter::Link(to = "/", "Home")
),
tags$li(
reactRouter::Link(to = "/dashboard", "Dashboard")
),
tags$li(
reactRouter::Link(to = "/nothing-here", "Nothing Here")
)
)
),
tags$hr(),
# An <Outlet> renders whatever child route is currently active,
# so you can think about this <Outlet> as a placeholder for
# the child routes we defined above.
reactRouter::Outlet()
)
reactRouter::HashRouter(
div(
style = "border:1px solid black;", # add border just for the example
h1("Basic Example"),
tags$p(
paste0('This example demonstrates some of the core features of React Router
including nested reactRouter::Route(), reactRouter::Outlet(),
reactRouter::Link(), and using a "*" route (aka "splat route")
to render a "not found" page when someone visits an unrecognized URL.'
)
),
reactRouter::Routes(
Route(
path = "/",
element = Layout,
Route(
index = TRUE,
element = div(
tags$h2("Home"),
tags$p("Home content")
)
),
Route(
path = "dashboard",
element = div(
tags$h2("Dashboard"),
tags$p("Dashboard here")
)
),
# Using path="*"" means "match anything", so this route
# acts like a catch-all for URLs that we don't have explicit
# routes for.
Route(
path = "*",
element = div(
tags$h2("Nothing to see here!"),
tags$p(
Link(to = "/", "Go to the home page")
)
)
)
)
)
)
)
A minimal example using dynamic segments, i.e. using
Route(to = ":id/*")
.
library(shiny)
library(reactRouter)
library(bslib)
ui <- HashRouter(
bslib::page(
Link(
to = "/",
h3("reactRouter with dynamic routes", class = "m-3"),
style = "text-decoration: none; color: black"
),
Routes(
Route(
path = "/",
element = div(
# tags$a() necessary to observe `url_hash` in session
NavLink(
to = "project/1/overview",
"Project 1"
),
tags$br(),
NavLink(
to = "project/2/overview",
"Project 2"
)
)
),
Route(
path = "project/:id/*",
element = div(
NavLink(
to = "overview",
"Overview"
),
tags$br(),
NavLink(
to = "analysis",
"Analysis"
),
Outlet()
),
children = list(
reactRouter::Route(
path = "overview",
element = uiOutput("uiOverview")
),
reactRouter::Route(
path = "analysis",
element = uiOutput("uiAnalysis")
)
)
)
)
)
)
server <- function(input, output, session) {
url_hash <- shiny::reactiveVal(value = NA)
# update reactive values based on url hash
observeEvent(session$clientData$url_hash, {
current_url_hash <- session$clientData$url_hash
print(current_url_hash)
url_hash(current_url_hash)
})
output$uiOverview <- renderUI({
url_hash()
})
output$uiAnalysis <- renderUI({
url_hash()
})
}
shinyApp(ui, server)
Run a more advanced example of dynamic routes with:
reactRouter implements React Router v.6.30.0.
More info about how to use React Router can be found in the official website.
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.