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 🙏

© 2024 – Pkg Stats / Ryan Hefner

use-stable-reference

v1.1.2

Published

Simple React hooks to access referentially stable, up-to-date versions of non-primitives.

Downloads

14

Readme

use-stable-reference

Simple React hooks to access referentially stable, up-to-date versions of non-primitives.

version bundle size downloads per week license dependencies

Basic usage

import { useStableCallback, useStableValue } from "use-stable-reference";

function Library({ unstableCallback, unstableValue }) {
  const stableCallback = useStableCallback(unstableCallback);
  const getStableValue = useStableValue(unstableValue);

  useEffect(() => {
    if (/* ... */) {
      stableCallback()
      const stableValue = getStableValue()
    }

    // safe to add to dependency arrays!
  }, [stableCallback, getStableValue, /* ... */]);
}

use-stable-reference really shines for library authors or for those writing reusable code. With a library-consumer relationship, the library author can't reasonably expect that the consumer will preemptively wrap any callbacks in a useCallback, or any referentially unstable values in a useMemo. This leaves the author with a few possible choices for how to handle consumer-provided non-primitive arguments:

  1. Leave them out of any dependency arrays, and ignore any eslint React linter warnings/errors
  2. Leave them in the dependency arrays, expecting that the effects / memoizations will run every render
  3. Wrap them in a useStableCallback/useStableValue

With option 3, the returned callback/value-getter are referentially stable, can safely be used in dependency arrays, and are guaranteed to always be up-to-date if the underlying option ever changes! 🎉

API

useStableCallback

useStableCallback accepts one argument, a callback of type: (...args: any[]) => any

useStableCallback returns an up-to-date, referentially stable callback.

useStableValue

useStableValue accepts one argument, a value of type: unknown

useStableValue returns a referentially stable callback that returns an up-to-date copy of the argument.

FAQ

Haven't I seen this before?

A version of this hook has been floating around the React community for a while, often referred to as useEvent or useEffectCallback. This package hopes to distill the best aspects of several different implementations:

Isn't updating a ref in the render method a bad practice?

Updating a ref in the render method is only dangerous when using concurrent features. Consider the following scenario:

  1. A component re-renders, i.e. the render method runs
  2. The ref is updated
  3. The DOM updates are discarded because a second, higher-priority render was triggered
  4. The higher-priority render occurs
  5. Any code which uses the ref value before it's updated in step 6 is using a value from a render that was discarded!
  6. The ref is updated to the intended value

Thankfully, this is rarely something we need to worry about, for a few reasons:

  1. Concurrent mode is opt-in, triggered only when using concurrent features
  2. Concurrent features are only available in React 18+
  3. The React compiler, which will make this library unnecessary, is in beta starting with React 19
  4. The callbacks and values that are passed to useStableCallback and useStableValue may be referentially unstable, but generally have the same behavior from render to render

In other words, for developers using React < 18, there's no issue because concurrent features aren't available; for devs using React > 19, you shouldn't need this package at all because of the React compiler; for those stuck in the middle using React 18, there's a good chance all the ref values will have the same behavior anyway, as long as you pass a callback/value with the same behavior every render.

That leaves just one scenario to consider. For devs using React 18, with concurrent features, with dynamic callbacks/values, consider yourselves warned: your refs may be out-of-sync with your render!