npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@posit-dev/shinyreact

v0.1.1

Published

React hooks and components for Shiny (shinyreact) — the ui.tsx pattern's client runtime

Readme

@posit-dev/shinyreact

check-js npm

React hooks and components for Shiny. The Shiny server — Python or R — contains only reactive computation, and the UI is a React client you own. This package is the bridge, and it ships zero UI components: no buttons, no layout, no theme. You bring the component library.

One React client works against an app.py or an app.R server unchanged. The full site covers all three packages.

Do you need this package?

Only if you use a bundler. shinyreact apps come in two tiers:

  • No build step — the server serves the same runtime as an IIFE and the client reads it off window.shinyreact. Nothing to install; you can stop reading.
  • Bundler (Vite, esbuild, webpack) — npm install this package and import the hooks. You get types, tree-shaking, a development React with Fast Refresh, and your own dependency graph.

Both tiers are built from the same source and speak the same protocol version.

Installation

npm install @posit-dev/shinyreact react react-dom

React 19 is a peer dependency, resolved by your bundler.

Then tell the page entry point that the client brings its own copy, so the server does not also serve the IIFE:

set_react_page(shinyreact_js="client")   # or page_react(), page_react_html(), ReactApp()
page_react(shinyreact_js = "client")

Skip that and the app still works — the registries are page-scoped, so both copies share one set of inputs, outputs, and message handlers — but the page downloads and parses a second React for nothing. The bundle logs a console.warn when it detects this.

Usage

import { useShinyInput, useShinyOutputValue } from "@posit-dev/shinyreact";
import "@posit-dev/shinyreact/styles";
import { createRoot } from "react-dom/client";

function App() {
  const [name, setName] = useShinyInput("name", "world");
  const greeting = useShinyOutputValue("greeting");

  return (
    <div>
      <input value={name} onChange={(e) => setName(e.target.value)} />
      <p>{greeting}</p>
    </div>
  );
}

// The page entry points emit no mount container, so make one.
createRoot(document.body.appendChild(document.createElement("div"))).render(
  <App />,
);

useShinyInput writes to input.name() / input$name on the server; useShinyOutputValue reads whatever the matching reactive_output returned:

@reactive_output
def greeting():
    return f"Hello, {input.name()}!"
output$greeting <- reactive_output({
  paste0("Hello, ", input$name, "!")
})

The "./styles" export is only needed for components that ship CSS (ImageOutput's placeholder spinner); the hooks have no styles of their own.

API

| | | | -------------- | ---------------------------------------------------------------------- | | Inputs | useShinyInput · useShinyInputValue · useSetShinyInput | | Outputs | useShinyOutputValue · useShinyOutputStatus · useShinyOutputError | | Messaging | useShinyMessageHandler | | Session | useShinyInitialized · useShinyBusy | | Components | ShinyOutput · ImageOutput · ShinyModuleProvider | | Utilities | MISSING · PROTOCOL_VERSION |

Pick the narrowest hook that fits the call site: a button that pushes events but never reads its own state wants useSetShinyInput, not useShinyInput with a discarded value.

ShinyOutput renders a traditional Shiny output element — a shiny-data-frame, a plotly widget — inside a React tree, and handles binding for you.

Full signatures and types: JS API reference.

Try it

git clone https://github.com/posit-dev/shinyreact
cd shinyreact/examples/11-npm-local
shiny run app.py                 # builds the client bundle on first run

Learn more

License

MIT © Posit Software, PBC