Open ElianHugh opened 1 year ago
Leaning toward the idea of isolated reactives, but this would ideally need a nice interface. Some ideas:
data = function() {
list(
x = reactive_value()
)
}
Issues with this approach:
props = function() {
list()
}
This creates a nice flow of props to data when passing values. E.g.
x <- component(
state = function() {
list(
rctv = 1L
)
}, template = function(ns) {
y(data = list(a = self$rctv))
}
)
y <- component() {
data = function() {
list(
a = NULL
)
}
}
Also ensures that the state cannot be modified outside the component (because only data can be passed between components)
Issues:
New component property: state
Steps to implementation:
Add state arguments to component generator functions https://github.com/ElianHugh/rsx/blob/68cca166ae158cce69ebebab378e5075c2167766/R/component.R#L15 https://github.com/ElianHugh/rsx/blob/68cca166ae158cce69ebebab378e5075c2167766/R/component.R#L20-L27 https://github.com/ElianHugh/rsx/blob/68cca166ae158cce69ebebab378e5075c2167766/R/component.R#L35
Add state attribute to component generator function
https://github.com/ElianHugh/rsx/blob/68cca166ae158cce69ebebab378e5075c2167766/R/component.R#L37-L49
https://github.com/ElianHugh/rsx/blob/68cca166ae158cce69ebebab378e5075c2167766/R/component.R#L52
Create wrapper class for state values (may have to re-implement shiny accessor methods)
Generate state values inside instance via instantiator function https://github.com/ElianHugh/rsx/blob/68cca166ae158cce69ebebab378e5075c2167766/R/instance.R#L34-L41
Add state values (reactiveVals) to instance self
environment
https://github.com/ElianHugh/rsx/blob/68cca166ae158cce69ebebab378e5075c2167766/R/instance.R#L50
Create active binding "state" alongside "data" and "method" bindings in instance https://github.com/ElianHugh/rsx/blob/68cca166ae158cce69ebebab378e5075c2167766/R/instance.R#L72-L91
Add testthat tests for state
component data is intentionally isolated from other components so as to encourage comprehensible component hierarchies. however, there are situations where accessing component data externally (and non-hierarchically) is a requirement.
Possible solutions
Hierarchical reactive data
One method of hierarchical and reactive data sharing is via defining reactive values on a top-level component and passing those along to subsequent child components.
E.g.
Barring the eventuality of a long chain of data passing, this has issues with understanding how data may mutate
Event bus
Like how vue does it -- basically just an event emitter
Isolated reactives
Wrapper class around
shiny::reactiveVal
and/orshiny::reactiveValues
that isolates value access from the children of components with data. E.g.stateful object
Object that contains reactive values that can be accessed in any component, similar to vuex
callback (child to parent)