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-resilience-kit

v0.2.0

Published

Enterprise-grade React error resilience: async errors, promise rejections, retry, recovery and logging with zero boilerplate.

Readme

react-resilience-kit

React resilience primitives for render failures, browser errors, rejected promises, async operations, retries, recovery, and pluggable error reporting.

Requirements

  • React 18 or newer
  • Node.js 16 or newer for package tooling

Install

npm install react-resilience-kit

Quick start

ResilienceProvider installs a root render boundary, captures browser errors and unhandled promise rejections, and enables the built-in console adapter.

import { ResilienceProvider } from "react-resilience-kit";

root.render(
  <ResilienceProvider>
    <App />
  </ResilienceProvider>,
);

The default fallback displays the error message and provides a reset button. Use ErrorGuard to isolate a smaller part of the tree or to provide a different fallback:

import { ErrorGuard } from "react-resilience-kit";

function App() {
  return (
    <ErrorGuard>
      <Dashboard />
    </ErrorGuard>
  );
}

The provider catches render, lifecycle, and constructor errors from its children. A boundary cannot catch errors thrown inside event handlers; use useAsyncGuard or useErrorReporter for those operations.

Fallback UI

Use the built-in minimal preset, a React component receiving error and reset, or a React element:

function AppFallback({ error, reset }: { error: unknown; reset: () => void }) {
  return (
    <section role="alert">
      <h1>Dashboard unavailable</h1>
      <p>{error instanceof Error ? error.message : "Unknown error"}</p>
      <button type="button" onClick={reset}>
        Try again
      </button>
    </section>
  );
}

<ResilienceProvider fallback={AppFallback}>
  <App />
</ResilienceProvider>;

Custom fallback text and actions

The package keeps sensible defaults, but consumers can override the default labels and content without replacing the whole fallback component. fallbackOptions accepts a small UI config and is merged with the built-in defaults.

<ResilienceProvider
  fallbackOptions={{
    title: "Dashboard unavailable",
    message: (error) => (error instanceof Error ? error.message : "Unexpected dashboard error"),
    retryLabel: "Retry dashboard data",
    resetLabel: "Reset dashboard",
    reloadLabel: "Refresh page",
  }}
>
  <App />
</ResilienceProvider>

You can also pass a custom fallback component and still use the same configuration object:

function AppFallback({ error, reset, retry, reload, ui }: FallbackProps) {
  return (
    <section role="alert">
      <h2>{ui?.title ?? "Something went wrong"}</h2>
      <p>{typeof ui?.message === "function" ? ui.message(error) : ui?.message}</p>
      {retry && <button onClick={retry}>{ui?.retryLabel ?? "Try again"}</button>}
      <button onClick={reset}>{ui?.resetLabel ?? "Reset"}</button>
      {reload && <button onClick={reload}>{ui?.reloadLabel ?? "Reload page"}</button>}
    </section>
  );
}

<ResilienceProvider fallback={AppFallback} fallbackOptions={{ title: "Dashboard unavailable" }}>
  <App />
</ResilienceProvider>;

Async operations

useAsyncGuard reports a rejected operation and rethrows the original error, so the calling component can still update its own loading and error state.

import { useAsyncGuard } from "react-resilience-kit";

function Users() {
  const { execute } = useAsyncGuard();

  async function loadUsers() {
    return execute(
      () =>
        fetch("/api/users").then((response) => {
          if (!response.ok) throw new Error("Unable to load users");
          return response.json();
        }),
      { zone: "users" },
    );
  }

  return (
    <button type="button" onClick={() => void loadUsers()}>
      Load users
    </button>
  );
}

The library does not force a failure message or button label. Apps can own that UI completely and keep their own copy, for example:

const uiLabels = {
  loading: "Loading team members...",
  error: "Unable to load team members after retries.",
  retry: "Retry team data",
  primary: "Load team members",
};

// The app decides exactly what to show when the async call fails.

Retry

Retries can be configured for the whole provider or for one operation. attempts includes the initial invocation.

<ResilienceProvider retry={{ attempts: 3, strategy: "exponential", delay: 500 }}>
  <App />
</ResilienceProvider>
const result = await execute(fetchUsers, {
  retry: { attempts: 4, strategy: "fibonacci", delay: 250 },
});

Available strategies:

  • linear: waits the base delay before each retry.
  • exponential: waits delay, 2 * delay, 4 * delay, and so on.
  • fibonacci: waits Fibonacci multiples of the base delay.
  • custom: calls delayStrategy(attempt) and expects milliseconds.

The lower-level helper is also available:

import { executeWithRetry } from "react-resilience-kit";

const value = await executeWithRetry(fetchUsers, {
  attempts: 3,
  strategy: "linear",
  delay: 500,
});

Reporting adapters

The console adapter is active by default. Supply a custom adapter through reporting.adapter:

const myLogger = {
  captureError(error, meta) {
    sendToMonitoring({ error, meta });
  },
  captureMessage(message, meta) {
    sendToMonitoring({ message, meta });
  },
  identifyUser(userId, traits) {
    sendUserToMonitoring(userId, traits);
  },
  flush() {
    return Promise.resolve();
  },
};

<ResilienceProvider reporting={{ adapter: myLogger }}>
  <App />
</ResilienceProvider>;

An adapter implements:

interface LoggerAdapter {
  captureError(error: unknown, meta: ErrorMeta): void;
  captureMessage(message: string, meta?: Partial<ErrorMeta>): void;
  identifyUser(userId: string, traits?: Record<string, unknown>): void;
  flush(): Promise<void>;
}

Only one active adapter is used by the provider. consoleAdapter is exported for direct use or testing.

Manual reporting

import { useErrorReporter } from "react-resilience-kit";

function SaveButton() {
  const report = useErrorReporter();

  async function save() {
    try {
      await saveChanges();
    } catch (error) {
      report(error, { route: "/settings", extra: { action: "save" } });
    }
  }

  return (
    <button type="button" onClick={() => void save()}>
      Save
    </button>
  );
}

Supported metadata includes route, zone, componentStack, timestamp, source, and extra. The library supplies timestamp and source automatically; manual reports use source: "manual".

Recovery actions

import { useRecovery } from "react-resilience-kit";

function RecoveryControls() {
  const { retry, reset, reload } = useRecovery();

  return (
    <>
      <button type="button" onClick={retry}>
        Retry request
      </button>
      <button type="button" onClick={reset}>
        Reset boundary
      </button>
      <button type="button" onClick={reload}>
        Reload page
      </button>
    </>
  );
}
  • retry reruns the most recent operation started with useAsyncGuard.
  • reset resets the most recently mounted ErrorGuard.
  • reload calls window.location.reload() and has no effect during server-side rendering.

Public API

  • ResilienceProvider, ResilienceProviderProps
  • ErrorGuard, ErrorGuardProps, MinimalFallback
  • useAsyncGuard, UseAsyncGuardOptions
  • useRecovery, useErrorReporter, useResilienceContext
  • executeWithRetry, linearDelay, exponentialDelay, fibonacciDelay
  • consoleAdapter, ErrorManager, RecoveryManager
  • Public types: ErrorMeta, LoggerAdapter, RetryConfig, RetryStrategy, ReportingConfig, ResilienceConfig, FallbackProps, FallbackPreset, FallbackUIConfig, and ErrorSubscriber

Current scope and limitations

This is the Phase 1 MVP. analytics and autoChunkRecovery are accepted provider options for forward compatibility but are currently no-ops. Error zones, automatic chunk recovery, analytics, and third-party adapters are not included in this release.

Global browser handlers are installed when ResilienceProvider mounts and removed when it unmounts. The library does not prevent the browser's normal error behavior or automatically suppress rejected promises.

Validate before publishing

From the package directory, run:

npm install
npm run typecheck
npm run lint
npm run build
npm pack --dry-run

The package should contain the compiled dist files, README.md, LICENSE, and package.json. Do not commit or publish node_modules.

Publish to npm step by step

  1. Create an npm account at https://www.npmjs.com/signup and verify the email address.

  2. Open a terminal in this package directory.

  3. Check the package name is available:

    npm view react-resilience-kit name version

    If npm returns a published package, choose a different name or request access to that package.

  4. Log in interactively:

    npm login
    npm whoami
  5. Review the package contents and metadata:

    npm pack --dry-run
    npm pkg get name version main module types exports files
  6. Run the validation commands in the previous section.

  7. Increment the version. npm will reject publishing a version that already exists:

    npm version patch

    Use npm version minor for a backward-compatible feature or npm version major for a breaking API change.

  8. Publish the public package:

    npm publish --access public
  9. Verify the published package:

    npm view react-resilience-kit version
    npm install react-resilience-kit

Never put an npm token in source control or command history. For CI publishing, use npm trusted publishing or an npm automation token stored in the CI secret store.

License

MIT