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

@pravosleva/reactive-engine

v1.5.8-beta

Published

Reactive Engine

Readme

🚀 ReactiveEngine Core Framework

A lightweight, type-safe reactive engine built with TypeScript, featuring Dependency Injection and seamless React integration.

Instruction

🎯 What Problems This Library Solves

When building large-scale React applications, developers constantly run into architectural bottlenecks imposed by built-in state tools. @pravosleva/reactive-engine is designed to elegantly solve the following pain points:

  1. Unnecessary Over-Rendering:
  • The Problem: React Context API and traditional immutability-based stores (Redux/Zustand) force all components reading from that state slice to re-render whenever even a single deeply nested property changes.
  • The Solution: Fine-grained reactivity. Components micro-subscribe only to the specific primitive signals they display. State mutations update strictly the necessary DOM nodes.
  1. UI Tearing and Lags in React 18+:
  • The Problem: Under React Concurrent Mode, standard external state managers can lead to UI tearing, where different parts of the screen temporarily display asynchronous, mismatching data.
  • The Solution: The useReactiveValue hook is built on top of native useSyncExternalStore. This ensures absolute cross-component synchronization, shielding your interface from glitches and tearing.
  1. Expensive CPU Re-calculations:
  • The Problem: Heavy array filtration, sorting, or data analytics functions trigger re-evaluations on every parent re-render or whenever unrelated props shift.
  • The Solution: Lazy Computed properties with O(1) computation caching. The logic evaluates only when its underlying dependency signals change.
  1. Network Request Flooding (Race Conditions):
  • The Problem: A user rapidly clicking through catalog filters or pagination options spawns cascades of overlapping network requests. An older, slower request might resolve after a newer one, overwriting fresh data (Race Condition).
  • The Solution: The Resource utility automatically orchestrates native AbortController instances. Whenever dependency signals change, the previous pending fetch request is instantly cancelled at the browser's system level.
  1. Cascading UI Updates (Render Cascades):
  • The Problem: Updating 3–4 connected state parameters inside a single event handler prompts 3–4 sequential UI update ticks, clogging the Event Loop.
  • The Solution: 100% out-of-the-box automatic batching. The engine bundles all consecutive synchronous and asynchronous modifications into a single microtask, triggering exactly 1 final unified re-render.
  1. Memory Leaks in Dynamic Architectures:
  • The Problem: Dynamically instantiating computed properties (e.g., dynamically filtering an active tab) accumulates abandoned reactive effects in memory that continue to listen to global state updates forever.
  • The Solution: Built-in memory cleanup and computation memoization inside the core engine. The library hooks automatically trigger .destroy() on component unmount, seamlessly purging dead reactive effects from RAM.

📦 Installation

Install the package via your favorite package manager:

yarn add @pravosleva/reactive-engine

peerDependencies

{
  "@angular/core": ">=16.0.0",
  "react": "^18.0.0 || ^19.2.0",
  "react-dom": "^18.0.0 || ^19.2.0",
  "vue": ">=3.2.0"
}

React

import { AbstractService } from '@pravosleva/reactive-engine'
import { ReactiveEngine } from '@pravosleva/reactive-engine/react'

class Logic extends AbstractService {
  public counter = this.engine.signal<number>(0, 'example-01:signal:counter');

  public inc = () => {
    this.counter.value += 1
  }
}

const engine = new ReactiveEngine()

export const Example001 = () => {
  const logic = engine.inject(Logic)
  const counter = engine.use(logic.counter)

  return (
    <div>
      <div>Signal example</div>
      <code>{counter}</code>
      <div className={baseClasses.catSection}>
        <button onClick={logic.inc}>+ INC</button>
      </div>
    </div>
  )
}

Vue 3

<script setup lang="ts">
import { AbstractService } from '@pravosleva/reactive-engine'
import { ReactiveEngine } from '@pravosleva/reactive-engine/vue'

class CounterLogic extends AbstractService {
  public counter = this.engine.signal<number>(0, 'vue-example:counter');

  public inc = () => {
    this.counter.value += 1
  }
}

const engine = new ReactiveEngine()
const logic = engine.inject(CounterLogic)
const counter = engine.use(logic.counter)
</script>

<template>
  <div>
    <div>Vue 3 Signal Example</div>
    <code>{{ counter }}</code>
    <div>
      <button @click="logic.inc">
        + INC
      </button>
    </div>
  </div>
</template>

Angular 16+

import { Component } from '@angular/core'
import { AbstractService } from '@pravosleva/reactive-engine'
import { ReactiveEngine } from '@pravosleva/reactive-engine/angular'

class CounterLogic extends AbstractService {
  public counter = this.engine.signal<number>(0, 'angular-example:counter');

  public inc = () => {
    this.counter.value += 1;
  };
}

@Component({
  selector: 'app-counter-example',
  standalone: true,
  template: `
    <div>
      <div>Angular 16+ Signal Example</div>
      <code>{{ counter() }}</code>
      <div>
        <button (click)="logic.inc()">
          + INC
        </button>
      </div>
    </div>
  `,
  styleUrls: []
})
export class AngularCounterComponent {
  private engine = new ReactiveEngine();

  public logic = this.engine.inject(CounterLogic);

  public counter = this.engine.use(this.logic.counter);
}