It looks like simply returning self from getReactive() does indeed result in your code working in a shiny app! That solution is very elegant and works well. The one thing that bothers me about it is that it requires two variables, and there's a bit of a disconnect between the two - I have to use one variable for calling methods and one variable for following reactivity, which results in more bookkeeping.
The best solution I could come up with is not as elegant as yours, but I focused on trying to get away with having only one variable, not two. It doesn't work with reactive, only with reactiveVal, and it has a very ugly part that requires you to initialize the class and then pass it a pointer of itself. It also uses internal features of shiny that have no guarantee to stay the same in future versions. Here is what I came up with:
Person <- R6::R6Class(
"Person",
private = list(
name = "",
rv = NULL
),
public = list(
initialize = function(name) {
private$name <- name
},
print = function() {
cat("Person:", private$name)
},
changeName = function(newName) {
if (!is.null(private$rv)) {
get("rv", environment(private$rv))$private$dependents$invalidate()
}
private$name <- newName
},
add_shiny_rv = function(rv) {
private$rv <- rv
}
)
)
And to use it, I would need to do
pr <- reactiveVal(Person$new("Dean"))
isolate(pr()$add_shiny_rv(pr))
The good thing is that now pr() is used both for calling methods on the object, and for reactivity. But it's so hacky that I'm sure it's dangerous to use such code.
For completeness, here's the solution by @winston inclduing the tiny fix I mention at the top of this post:
library(shiny)
Person <- R6::R6Class(
"Person",
private = list(
name = "",
reactiveDep = NULL
),
public = list(
initialize = function(name) {
private$reactiveDep <- reactiveVal(0)
private$name <- name
},
print = function() {
cat("Person:", private$name, "\n")
},
changeName = function(newName) {
private$reactiveDep(isolate(private$reactiveDep()) + 1)
private$name <- newName
},
getReactive = function() {
private$reactiveDep()
self
}
)
)
p <- Person$new("Dean")
pr <- reactive(p$getReactive())