Appsilon / shiny.react

Use React in Shiny applications.
https://appsilon.github.io/shiny.react
GNU Lesser General Public License v3.0
96 stars 12 forks source link

Support accessor in `setInput()` #43

Closed kamilzyla closed 1 year ago

kamilzyla commented 2 years ago

Background

React components typically use handlers to notify parent about value changes, e.g. (Checkbox from Blueprint.js):

<Checkbox
  defaultChecked={false}
  onChange={(event) => handle(event.target.checked)}
/>

With shiny.react it is possible to use such a component in the following way:

Checkbox(
  defaultChecked = FALSE,
  onChange = JS('(event) => Shiny.setInputValue("checked", event.target.checked)')
)

However, it is inconvenient and error-prone to define the onChange handler using JS code embedded in a string, so we have

shiny.react::setInput(inputId, argIdx = 1)

which can be seen as equivalent to

(...args) => Shiny.setInputValue(inputId, args[argIdx - 1]) // JS uses 0-based indexing

Problem

The setInput() function currently only supports sending one of the arguments to Shiny server. It is insufficient when we need to do something with the argument first, like getting the .target.checked property in the Checkbox example above. It would be great if we could do something like this:

Checkbox(
  defaultChecked = FALSE,
  onChange = setInput("checked", "[0].target.value")
)

Approach

Consider replacing the argIdx argument of setInput with accessor which would behave as in the example above. Suggest other possible API ideas for setInput (e.g. have both argIdx and accessor arguments) and consult with reviewer before implementation.

Relevant files

  1. R/react.R:174: definition of setInput()
  2. js/src/react/mapReactData.js:88: JS-side handler