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

@composablearchitecture.io/react

v0.1.2

Published

React bindings for the Composable Architecture. Re-exports @composablearchitecture.io/core.

Readme

@composablearchitecture.io/react

React bindings for the Composable Architecture port. Provides a small set of components — WithStore, WithStore.observe, WithStore.ifLet, ForEachStore — that connect a Store to your React tree.

This package re-exports the entire @composablearchitecture.io/core API, so you only need a single dependency in a React app:

import {
  // core
  Store, Reducer, Effect,
  // react bindings
  WithStore, ForEachStore,
} from "@composablearchitecture.io/react";

Install

pnpm add @composablearchitecture.io/react react
# or
npm  install @composablearchitecture.io/react react

react (>=18) is a peer dependency. The core package is pulled in transitively — you do not need to install it yourself.

Quick Start

import { Reducer, Store, WithStore } from "@composablearchitecture.io/react";

type CounterAction = "increment" | "decrement" | "reset";

const counterReducer = Reducer.transform<number, CounterAction>(
  (state, action) => {
    switch (action) {
      case "increment": return state + 1;
      case "decrement": return state - 1;
      case "reset":     return 0;
    }
  },
);

const store = Store.initial(0, counterReducer, null);

export default function Counter() {
  return (
    <WithStore store={store}>
      {(count, send) => (
        <>
          <button onClick={() => send("decrement")}>-</button>
          <span>{count}</span>
          <button onClick={() => send("increment")}>+</button>
          <button onClick={() => send("reset")}>reset</button>
        </>
      )}
    </WithStore>
  );
}

A complete runnable example lives in examples/react-counter.

Components

<WithStore>

The basic connector. Subscribes to the store on mount and re-renders the children render-prop whenever the state fails the equality check (deep-equal by default). The render function receives the current state and a send function.

<WithStore store={store} isEqual={Object.is}>
  {(state, send) => <SomeView state={state} onAction={send} />}
</WithStore>

WithStore.observe

When a component cares about only a slice of state, project it through observe so the component re-renders only when the projection changes:

{WithStore.observe<AppState, number, AppAction>({
  store: appStore,
  observe: (s) => s.cart.items.length,
  children: (count, send) => <Badge count={count} />,
})}

Equivalent to appStore.scopeState((s) => s.cart.items.length) followed by a <WithStore>, but with a single, declarative call.

WithStore.ifLet

Renders children only while a projected slice is non-null, providing a Store scoped to the non-null slice. Use it for optional features (modals, drill-down screens, drawers) without sprinkling null-checks across the UI:

{WithStore.ifLet<AppState, DetailState | null, AppAction>({
  store: appStore,
  observe: (s) => s.detail,
  children: (detailStore) => <DetailView store={detailStore} />,
  orElse: <EmptyState />,
})}

Re-renders are limited to presence transitions (absent ↔ present); updates inside the slice are observed by the inner store.

<ForEachStore>

Renders one component per element of a collection held by a store, scoping each child to its own slice and routing item-level actions back into the parent via embedAction. Per-id stores are cached across renders, so children keep their identity (and React state) when neighbours update.

<ForEachStore<string, AppState, AppAction, TodoState, TodoAction>
  store={appStore}
  getIterable={(s) => s.todos}
  toID={(_, todo) => todo.id}
  embedAction={(id, action) => ({ type: "todo", id, action })}
  builder={(todoStore) => <TodoRow store={todoStore} />}
  onEmptyBuilder={() => <EmptyState />}
/>

The component re-renders only when the list of ids changes; updates inside an element are observed by that element's own scoped store.

Equality

WithStore and WithStore.observe accept an optional isEqual prop. The default is a hand-rolled deepEqual that handles arrays, plain objects, Map, Set, typed array views, and RegExp, and that intentionally ignores React's internal _owner field on rendered elements. Override isEqual with Object.is, a shallow comparator, or any custom function when you need different semantics.

Build

pnpm install
pnpm --filter @composablearchitecture.io/react build

License

MIT — see LICENSE.