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

@k8slens/use-inject

v1.0.2

Published

The hooks a React component injects with: useInject, and useSyncInject for values that must not suspend

Readme

@k8slens/use-inject

useInject — how a React component reads an injected value.

import { useInject } from "@k8slens/use-inject";

const MyPanel = () => {
  const getGreeting = useInject(greetingInjectable);

  return <p>{getGreeting()}</p>;
};

useInject hands back the injectable's factory, not the value. Calling it produces the value, and instantiation parameters go to that call rather than to useInject:

const getGreeting = useInject(greetingForNameInjectable);

return <p>{getGreeting("Ada")}</p>;

Why this package exists

The hook itself lives in @k8slens/injectable-react under the name useInject2. The 2 is an artefact of an internal DI migration and means nothing to a consumer, and that package also carries an older, differently behaved useInject from before the migration. So the name is claimed here, on a package small enough to promise to everyone, and consumers are spared both the digit and the ambiguity.

Asynchronous values: useSyncInject, never Suspense

When the value resolves later, use useSyncInject. It reads the value without suspending and re-renders when it changes. Unlike useInject it hands back the value, and a parameter goes to the hook:

const summary = useSyncInject(summaryForClusterInjectable, clusterId);

useInject will hand you a promise if the factory returns one, and React's use looks like the obvious next step. It is not. Suspense is incompatible with MobX observation here: React throws away a suspended render and retries it, mobx-react tracks the abandoned render's Reaction with a FinalizationRegistry, and so cleanup waits on garbage collection that may be late or never come. The observation outlives the component — onBecomeUnobserved never fires and each suspension leaves another live observer behind.

Verified in this repo, not inherited from a changelog: an observer that suspends still holds its observation after unmount, while a non-suspending one releases it. The code path is unchanged in the latest mobx-react-lite, and the upstream fix (mobxjs/mobx#3777) has never been merged.

Be careful what you pass as an instantiation parameter

The cache is keyed by reference. Primitives behave as expected — equal strings or numbers resolve to one instance — and a reference type is fine too, provided the reference is stable. What breaks is building the value inline, where identity differs on every render:

// Trouble: a new object each render is a new key each render.
getGreetingFor({ name });

// Fine: a primitive resolves to one instance.
getGreetingFor(name);

// Also fine: one stable reference.
const subject = useInject(currentSubjectInjectable)();
getGreetingFor(subject);

The cost of an unstable key is more than a re-suspension. Each render mints another instance the container then holds, so the cache grows unbounded while the component renders, and nothing is shared: two callers asking for "the same" thing get separate instances with separate state and separate observers.

So think about identity rather than type. A reference from DI, from props, or from a memo is as stable as a primitive; only a literal built inline is the hazard.