shinyreact
React UI infrastructure for Shiny — Python and R
With shinyreact, the Shiny server (Python or R) contains only reactive computation, and the UI is a React client you own. shinyreact is the bridge between the two; it ships zero UI components itself.
One JavaScript bundle backs both languages, so the same React client works identically against an app.py or an app.R server.
The ui.tsx pattern
- The app file bootstraps a static page —
set_react_page()(Python Express) orpage_react()(Python Core, R). - Your React client, conventionally
ui.tsx(compiled towww/ui.js, discovered automatically), renders the UI. - Client and server talk through hooks:
useShinyInputsends values to the server,useShinyOutputValuereceives whatreactive_outputpublishes, anduseShinyMessageHandlerreceivessend_message()pushes.
from shiny.express import input
from shinyreact import reactive_output, set_react_page
set_react_page()
@reactive_output
def greeting():
return {"message": f"Hello, {input.name()}"}library(shiny)
library(shinyreact)
server <- function(input, output, session) {
output$greeting <- reactive_output({
list(message = paste0("Hello, ", input$name))
})
}
shinyApp(page_react(), server)const { React, ReactDOM, useShinyInput, useShinyOutputValue } = window.shinyreact;
function App() {
const [name, setName] = useShinyInput("name", "world");
const greeting = useShinyOutputValue("greeting");
return (
<>
<input value={name} onChange={(e) => setName(e.target.value)} />
<p>{greeting?.message}</p>
</>
);
}
// No mount div in the generated page — append one to <body>.
ReactDOM.createRoot(document.body.appendChild(document.createElement("div"))).render(<App />);Installation
shinyreact is pre-release. Install from GitHub:
pip install "git+https://github.com/posit-dev/shinyreact.git"pak::pak("posit-dev/shinyreact/pkg-r")The JS hooks come with the server package — set_react_page() / page_react() serve shinyreact.js, which installs them at window.shinyreact. Apps with a bundler can instead npm install @posit-dev/shinyreact and pass shinyreact_js="client" to the page entry point.
Agent Skills
Both packages ship two Agent Skills so a coding agent can build a shinyreact app without you pasting documentation into it: shinyreact-build-app builds a ui.tsx-pattern app from scratch, and shinyreact-convert-app ports an existing Shiny app to the pattern.
The fastest starter template is the skill itself. With the shinyreact skills installed, paste this into your agent (swap in R if that is your server):
Using the `/shinyreact-build-app` skill, scaffold a new shinyreact app in this
directory with a Python server. Set up the Vite build (src/ui.tsx compiled to
www/ui.js) and a hello-world UI: a text input whose value the server greets by
name. Run the build and start the app.
Reference
| Python | set_react_page(), page_react(), ReactApp, reactive_output, send_message(), … |
| R | page_react(), reactive_output(), send_message(), … |
| JS | useShinyInput, useShinyOutputValue, useShinyMessageHandler, ShinyOutput, … |
| Examples | Runnable apps, from no-build www/ui.js to Vite + HMR |
| Design | Why the pattern looks the way it does |