Skip to content

Commit a6af4a2

Browse files
committed
Fix #4 using reloadDocument = TRUE. Update docs accordlingly. Also make key argument accessible in Route().
1 parent 5ed468e commit a6af4a2

7 files changed

Lines changed: 115 additions & 52 deletions

File tree

R/components.R

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,23 +45,26 @@ MemoryRouter <- component('MemoryRouter')
4545

4646
#' Route
4747
#'
48+
#' \url{https://reactrouter.com/6.30.0/components/route}
49+
#'
4850
#' Internally the `element` is wrapped in a `shiny::div()`
4951
#' with a UUID key so, in case R shiny is used, shiny can differentiate
5052
#' each element.
5153
#'
5254
#' @rdname Route
5355
#' @param ... Props to pass to element.
54-
#' @param element element with UUID key wrap in a `shiny::div()`.
56+
#' @param element element wrapped in a `shiny::div()`.
57+
#' @param key By default uses a UUID key in the `div()` of the `element` arg.
5558
#' @return A Route component.
5659
#' @export
57-
Route <- function(..., element) {
60+
Route <- function(..., element, key = uuid::UUIDgenerate()) {
5861
shiny.react::reactElement(
5962
module = "react-router-dom",
6063
name = "Route",
6164
props = shiny.react::asProps(
6265
...,
6366
element = shiny::div(
64-
key = uuid::UUIDgenerate(),
67+
key = key,
6568
element
6669
)
6770
),
@@ -70,12 +73,28 @@ Route <- function(..., element) {
7073
}
7174

7275
#' Link
76+
#'
77+
#' The `reloadDocument` can be used to skip client side routing and let the
78+
#' browser handle the transition normally (as if it were an <a href>). In
79+
#' React Router v6 `reloadDocument` if `FALSE`, but given shiny behavior, the
80+
#' `Link()` function makes it `TRUE` by default.
81+
#'
7382
#' @rdname Link
74-
#' @description \url{https://reactrouter.com/6.30.0/components/link}
7583
#' @param ... Props to pass to element.
84+
#' @param reloadDocument Boolean. Default TRUE. Let browser handle the transition normally
7685
#' @return A Link component.
7786
#' @export
78-
Link <- component('Link')
87+
Link <- function(..., reloadDocument = TRUE) {
88+
shiny.react::reactElement(
89+
module = "react-router-dom",
90+
name = "Link",
91+
props = shiny.react::asProps(
92+
...,
93+
reloadDocument = reloadDocument
94+
),
95+
deps = reactRouterDependency()
96+
)
97+
}
7998

8099
#' Navigate
81100
#' @rdname Navigate
@@ -86,12 +105,29 @@ Link <- component('Link')
86105
Navigate <- component('Navigate')
87106

88107
#' NavLink
108+
#'
109+
#' The `reloadDocument` can be used to skip client side routing and let the
110+
#' browser handle the transition normally (as if it were an <a href>). In
111+
#' React Router v6 `reloadDocument` if `FALSE`, but given shiny behavior, the
112+
#' `NavLink()` function makes it `TRUE` by default.
113+
#'
89114
#' @rdname NavLink
90-
#' @description \url{https://reactrouter.com/6.30.0/components/nav-link}
91115
#' @param ... Props to pass to element.
116+
#' @param reloadDocument Boolean. Default TRUE. Let browser handle the transition normally
92117
#' @return A NavLink component.
93118
#' @export
94-
NavLink <- component('NavLink')
119+
NavLink <- function(..., reloadDocument = TRUE) {
120+
shiny.react::reactElement(
121+
module = "react-router-dom",
122+
name = "NavLink",
123+
props = shiny.react::asProps(
124+
...,
125+
reloadDocument = reloadDocument
126+
),
127+
deps = reactRouterDependency()
128+
)
129+
}
130+
95131

96132
#' Outlet
97133
#' @rdname Outlet

R/inputs.R

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,56 @@
1-
input <- function(name) {
2-
function(inputId, ...) {
1+
input_link <- function(name) {
2+
function(inputId, ..., reloadDocument = TRUE) {
33
checkmate::assert_string(inputId)
44
shiny.react::reactElement(
55
module = "@/reactRouter",
66
name = name,
7-
props = shiny.react::asProps(inputId = inputId, ...),
7+
props = shiny.react::asProps(inputId = inputId, ..., reloadDocument = reloadDocument),
88
deps = reactRouterDependency()
99
)
1010
}
1111
}
1212

1313
#' Link
1414
#' @rdname Link
15-
#' @description \url{https://reactrouter.com/en/main/components/link}
15+
#' @description \url{https://reactrouter.com/6.30.0/components/link}
1616
#' @param ... Props to pass to element.
1717
#' @param inputId ID of the component.
18+
#' @param reloadDocument Boolean. Default TRUE. Let browser handle the transition normally
1819
#' @param session Object passed as the `session` argument to Shiny server.
1920
#' @export
20-
Link.shinyInput <- input('Link')
21+
Link.shinyInput <- function(inputId, ..., reloadDocument = TRUE) {
22+
checkmate::assert_string(inputId)
23+
checkmate::assert_logical(reloadDocument)
24+
shiny.react::reactElement(
25+
module = "@/reactRouter",
26+
name = "Link",
27+
props = shiny.react::asProps(inputId = inputId, ..., reloadDocument = reloadDocument),
28+
deps = reactRouterDependency()
29+
)
30+
}
2131

2232
#' @rdname Link
2333
#' @export
2434
updateLink.shinyInput <- shiny.react::updateReactInput
2535

2636
#' NavLink
2737
#' @rdname NavLink
28-
#' @description \url{https://reactrouter.com/en/main/components/nav-link}
38+
#' @description \url{https://reactrouter.com/6.30.0/components/nav-link}
2939
#' @param ... Props to pass to element.
3040
#' @param inputId ID of the component.
41+
#' @param reloadDocument Boolean. Default TRUE. Let browser handle the transition normally
3142
#' @param session Object passed as the `session` argument to Shiny server.
3243
#' @export
33-
NavLink.shinyInput <- input('NavLink')
44+
NavLink.shinyInput <- function(inputId, ..., reloadDocument = TRUE) {
45+
checkmate::assert_string(inputId)
46+
checkmate::assert_logical(reloadDocument)
47+
shiny.react::reactElement(
48+
module = "@/reactRouter",
49+
name = "NavLink",
50+
props = shiny.react::asProps(inputId = inputId, ..., reloadDocument = reloadDocument),
51+
deps = reactRouterDependency()
52+
)
53+
}
3454

3555
#' @rdname NavLink
3656
#' @export

inst/examples/dynamic-segment/app.R

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -124,19 +124,15 @@ ui <- reactRouter::HashRouter(
124124

125125
server <- function(input, output, session) {
126126

127-
# issue #4: https://github.com/lgnbhl/reactRouter/issues/4
128-
# NOT NECESSARY AS WE NEED ONLY PROJECT ID, WORKING WITHOUT RELOADING THE SESSION
129-
# observeEvent(c(input$home, input$overview, input$analysis), {
130-
# session$reload()
131-
# })
132-
127+
url_hash <- shiny::reactiveVal(value = NA)
133128
url_hash_cleaned <- shiny::reactiveVal(value = NA)
134129

135130
# update reactive values based on url hash
136131
shiny::observe({
137132
current_url_hash <- sub("#/", "", session$clientData$url_hash)
138133
# print(current_url_hash)
139-
134+
url_hash(current_url_hash)
135+
140136
# extract numeric id from current url hash
141137
current_url_hash_cleaned <- as.integer(stringr::str_extract(current_url_hash, "\\d+"))
142138
# print(current_url_hash_cleaned)
@@ -185,6 +181,10 @@ server <- function(input, output, session) {
185181
class = "p-3",
186182
card(
187183
card_header("Session and data"),
184+
tags$p(
185+
tags$b("Current hash url: "),
186+
paste0("'", url_hash(), "'")
187+
),
188188
tags$p(
189189
tags$b("Current cleaned hash url: "),
190190
paste0("'", url_hash_cleaned(), "'")
@@ -235,6 +235,10 @@ server <- function(input, output, session) {
235235
class = "p-3",
236236
card(
237237
card_header("Session and data"),
238+
tags$p(
239+
tags$b("Current hash url: "),
240+
paste0("'", url_hash(), "'")
241+
),
238242
tags$p(
239243
tags$b("Current cleaned hash url: "),
240244
paste0("'", url_hash_cleaned(), "'")

man/Link.Rd

Lines changed: 9 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/NavLink.Rd

Lines changed: 9 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/Route.Rd

Lines changed: 7 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vignettes/introduction.Rmd

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -90,15 +90,13 @@ reactRouter::HashRouter(
9090
nav_item(
9191
reactRouter::NavLink(
9292
"Home",
93-
to = "/",
94-
style = JS('({isActive}) => { return isActive ? {color: "red", textDecoration: "none"} : {}; }')
93+
to = "/"
9594
)
9695
),
9796
nav_item(
9897
reactRouter::NavLink(
9998
"Analysis",
100-
to = "/analysis",
101-
style = JS('({isActive}) => { return isActive ? {color: "red", textDecoration: "none"} : {}; }')
99+
to = "/analysis"
102100
)
103101
),
104102
reactRouter::Routes(
@@ -326,17 +324,14 @@ reactRouter::HashRouter(
326324

327325
A minimal example using dynamic segments, i.e. using `Route(to = ":id/*")`.
328326

329-
If you want to observe the `url_hash` of the shiny session, you need to use a workaround ([issue #4](https://github.com/lgnbhl/reactRouter/issues/4)) to get the correct `url_hash` path by reloading the session when the user click on a link, as showed below:
330-
331327
```r
332328
library(shiny)
333329
library(reactRouter)
334330
library(bslib)
335331

336332
ui <- HashRouter(
337333
bslib::page(
338-
reactRouter::Link.shinyInput(
339-
inputId = "home",
334+
Link(
340335
to = "/",
341336
h3("reactRouter with dynamic routes", class = "m-3"),
342337
style = "text-decoration: none; color: black"
@@ -346,28 +341,26 @@ ui <- HashRouter(
346341
path = "/",
347342
element = div(
348343
# tags$a() necessary to observe `url_hash` in session
349-
tags$a(
350-
href = "#/project/1/overview",
344+
NavLink(
345+
to = "project/1/overview",
351346
"Project 1"
352347
),
353348
tags$br(),
354-
tags$a(
355-
href = "#/project/2/overview", # go directly to overview
349+
NavLink(
350+
to = "project/2/overview",
356351
"Project 2"
357352
)
358353
)
359354
),
360355
Route(
361356
path = "project/:id/*",
362357
element = div(
363-
NavLink.shinyInput(
364-
inputId = "overview",
358+
NavLink(
365359
to = "overview",
366360
"Overview"
367361
),
368362
tags$br(),
369-
NavLink.shinyInput(
370-
inputId = "analysis",
363+
NavLink(
371364
to = "analysis",
372365
"Analysis"
373366
),
@@ -390,11 +383,6 @@ ui <- HashRouter(
390383

391384
server <- function(input, output, session) {
392385

393-
# Necessary to update `url_hash` to get "" (homepage), "1/analysis" and "2/analysis"
394-
observeEvent(c(input$home, input$overview, input$analysis), {
395-
session$reload()
396-
})
397-
398386
url_hash <- shiny::reactiveVal(value = NA)
399387

400388
# update reactive values based on url hash

0 commit comments

Comments
 (0)