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

react-use-refs

v1.0.1

Published

Hook to create multiple refs in a single call

Downloads

2,617

Readme

useRefs ♻️

React hook to create multiple refs in a single call.

Usage

Instead of calling useRef many times, you just call useRefs and destructure as many refs as you want!

import useRefs from "react-use-refs";

const [someRef, anotherRef] = useRefs();

The first and only argument is the initialValue of the refs. There’s no way to specify a different value for each ref. Use a list of React.useRefs for that!

TypeScript support

This library supports TypeScript and should work exactly as React.useRef does.

const [cardRef, cardBodyRef] = useRefs<HTMLDivElement>();

return <div ref={cardRef}> ... </div>;

If you want to have multiple ref types, then you can pass a tuple and have it spread onto the created refs:

const [cardRef, inputRef] = useRefs<[HTMLDivElement, HTMLInputElement]>(null);

⚠️ Passing null as the initialValue is required for tuples!

Frequently Asked Questions

🧙‍♀️ Is this black magic?

No. Keep reading.

🤔 So how does this work?!

This hook returns an iterable object, something you can use in a for (of) statement, with Array.from() or (and this is the neat part) with the Array Destructuring syntax (the one you use for state/setState pairs for example.)

Also, if you have a look at the code the returned value from the iterator has always the done flag set to false. This is an infinite loop disguised as an iterator! But since calling next during array destructuring happens a finite number of times, hence we do not hit typical infinte loop behaviour (aka frozen page).

📜 Does this break the Rules of Hooks?

Short answer: no. Real answer: it’s up to you. Actual real answer follows.

The Rules of Hooks section of React’s official documentation cite: Don’t call Hooks inside loops, conditions, or nested functions.

As you can see in the source code we are definitely breaking this rule by calling useRef inside the next() method of the Iterable.

But we need to understand the the Rules of Hooks exist for a reason, and that is to have statically stable invocation of primitive hooks between re-renders.

Since we explicitly encourage the use of Array Destructuring, the dynamic part is made “static” by hard-coding it in your own source code. We therefore do not break the rules of hooks.

😈 But wait I can manually call .next() conditionally!

Yeah, you can do some bad stuff with the returned iterator, but it’s not that different from having, for example, the following code:

const iSwearIAmNotUseRef = React.useRef();

The only issue is that using the returned iterator doesn’t throw a ESLint warning at you as the above code would.

😕 Ok, but why did you do it?

Because I could. And because @drcmda said he would use it and would love it. ❤️ Spread love and not some silly questions about what people do in their free time.

Credits

  • Thanks to @drcmda for stating his need for such an API.
  • Thanks to @Andarist for the initial TypeScript types definition.

License

MIT