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

react-contextless

v1.0.0

Published

A backend-style runtime for React with middleware, DI, plugins, and structured action execution.

Readme

⚡ react-contextless

NPM Downloads Bundle Size

LIVE EXAMPLE

🚀 A reactive service runtime for React applications.

Build scalable frontend systems using reactive services, computed state, batching, and runtime orchestration — without Context providers or reducer boilerplate.


What is react-contextless?

react-contextless is a lightweight runtime framework for React applications.

It combines:

  • reactive services
  • service containers
  • batching
  • computed state
  • runtime orchestration
  • selector-based subscriptions

into a single runtime layer.

Unlike traditional React state libraries, it focuses on:

  • service-oriented architecture
  • explicit runtime orchestration
  • external reactive systems
  • framework-agnostic business logic

Why react-contextless?

Modern frontend applications often suffer from:

business logic inside components

  • prop drilling
  • provider nesting
  • duplicated async state handling
  • inconsistent orchestration
  • tightly coupled UI state

react-contextless solves this by introducing a runtime execution layer:

  • services hold business logic
  • React becomes a rendering adapter
  • state lives outside component trees
  • orchestration becomes explicit
  • services communicate through reactive runtime updates

Features

  • ⚡ Reactive service architecture
  • 🧠 Service container runtime
  • 🚫 No Context provider required
  • ⚛️ React 18 useSyncExternalStore
  • 🔥 Batched reactive updates
  • 🧩 Computed / derived state
  • 🌐 Cross-service reactivity
  • 📦 Singleton service runtime
  • 🔌 Async factory injection
  • 🛡 Stable concurrent rendering
  • 🧱 Framework-agnostic core
  • ✨ Tiny runtime footprint

Mental Model

UI
 ↓
useService()
 ↓
React Bridge
 ↓
Reactive Runtime
 ↓
Services
 ↓
Service Container
 ↓
Business Logic

Installation

npm install react-contextless

Quick Example

Create Tokens

// tokens.ts
import { createToken } from 'react-contextless'

import type { ApiService } from './services/api'
import type { AuthService } from './services/auth'

export const ApiToken = createToken<ApiService>('ApiService')
export const AuthToken = createToken<AuthService>('AuthService')

Create Services

Api Service

// services/api.ts
export class ApiService {
  async getUser() {
    return { id: '1', name: 'Tung' }
  }
}

Auth Service

// services/auth.ts
import { ReactiveService } from 'react-contextless'
import { ApiToken } from '../tokens'
import type { ApiService } from './api'

export class AuthService extends ReactiveService {
  static inject = [ApiToken]
  user: any = null

  constructor(private api: ApiService) {
    super()
  }

  async login() {
    this.user = await this.api.getUser()
    this.emit()
  }

  logout() {
    this.user = null
    this.emit()
  }
}

Create App Runtime

// app.ts
import { createApp } from 'react-contextless'
import { ApiToken, AuthToken } from './tokens'
import { ApiService } from './services/api'
import { AuthService } from './services/auth'

export const app = createApp([
  { token: ApiToken, useClass: ApiService },
  { token: AuthToken, useClass: AuthService },
])

Create React Bridge

// runtime.ts
import { createBridge } from 'react-contextless'
import { app } from './app'

export const useService = createBridge(app)

React Usage

// App.tsx
import { useService } from './runtime'
import { AuthToken } from './tokens'

export function App() {
  const auth = useService(AuthToken)

  return (
    <div>
      <button onClick={() => auth.login()}>Login</button>
      <pre>{JSON.stringify(auth.user, null, 2)}</pre>
    </div>
  )
}

Service Dependencies

Services can depend on other services

export class AuthService {
  static inject = [ApiToken]
  constructor(private api: ApiService) {}
}

Async Factory Injection

const app = createApp([
  {
    token: ApiToken,
    async useFactory() {
      const api = await createApi()
      return api
    },
  },
])

Reactive Services

Reactive services automatically notify React subscribers:

import { ReactiveService } from 'react-contextless'

export class CounterService extends ReactiveService {
  count = 0

  increment() {
    this.count++
    this.emit()
  }
}

useService

const counter = useService(CounterToken)

Selector Subscriptions

Subscribe only to specific values:

const count = useService(CounterToken, (s) => s.count)
// Re-render occurs only if the selected value changes

Re-render occurs only if the selected value changes.


Computed State

Derived reactive state:

import { createComputed } from 'react-contextless'

const fullName = createComputed(
  () => `${user.first} ${user.last}`,
  [userService]
)

Cross-Service Reactivity

Services can react to other services:

export class ProfileService {
  profile: any

  constructor(auth: AuthService) {
    const computed = createComputed(
      () => ({ name: auth.user?.name ?? 'Guest' }),
      [auth]
    )
    this.profile = computed.get
  }
}

Batching

Multiple updates are batched automatically:

counter.increment()
counter.increment()
counter.increment()

Single render tick


Scoped Containers

Create isolated runtime scopes:

const scope = app.createScope()

Useful for:

  • route-level isolation
  • modal runtime state
  • micro-frontends
  • sandbox execution

Runtime Architecture

Services
   ↓
Reactive Runtime
   ↓
Batch Scheduler
   ↓
React Bridge
   ↓
UI

Full Example

import React from 'react'

import {
  createApp,
  createBridge,
  createToken,
  ReactiveService,
} from 'react-contextless'

class CounterService
  extends ReactiveService
{
  count = 0

  increment() {
    this.count++

    this.emit()
  }
}

const CounterToken =
  createToken<CounterService>(
    'CounterService',
  )

const app = createApp([
  {
    token: CounterToken,
    useClass: CounterService,
  },
])

const useService =
  createBridge(app)

export function App() {
  const counter =
    useService(
      CounterToken,
      (s) => s.count,
    )

  const service =
    useService(CounterToken)

  return (
    <button
      onClick={() => {
        service.increment()
      }}
    >
      Count: {counter}
    </button>
  )
}

Comparison

| Criteria | react-contextless. | React Context | Zustand | Redux | | -------------------------- | ----------------------| ------------- | ------- | ------ | | No Provider | ✅ | ❌ | ✅ | ❌ | | Service Container | ✅ | ❌ | ❌ | ❌ | | Reactive Services | ✅ | ❌ | ⚠️ | ❌ | | Computed State | ✅ | ⚠️ | ⚠️ | ❌ | | Batch Runtime | ✅ | ❌ | ⚠️ | ⚠️ | | Cross-Service Reactivity | ✅ | ❌ | ❌ | ❌ | | Selector Rendering | ✅ | ❌ | ✅ | ✅ | | Backend-style Architecture | ✅ | ❌ | ❌ | ⚠️ | | External Runtime Logic | ✅ | ❌ | ⚠️ | ⚠️ |


Core Concepts

Services contain business logic and runtime state.

class AuthService extends ReactiveService {}

Design Principles

  • Explicit runtime execution
  • Service-oriented frontend architecture
  • Composition over inheritance
  • Deterministic reactive updates
  • Minimal runtime abstraction
  • Framework-agnostic business layer

When to Use

  • Large React applications
  • Complex frontend architectures
  • Service-oriented frontend systems
  • Runtime orchestration
  • Plugin-driven applications
  • Shared business logic layers
  • Backend/frontend architecture alignment

When NOT to Use

  • Tiny local component state
  • Simple forms
  • Minimal UI prototypes
  • Reducer-first immutable architectures

Publish

export {
  createApp,
  createToken,
  ReactiveService,
  createBridge,
  createComputed,
  batch,
}

License

MIT