react-use
react-use copied to clipboard
Split packages
Is your feature request related to a problem? Please describe. A somewhat follow up of #384, I would like to use this package with the minimum amount of dependencies pulled in.
Describe the solution you'd like
I should be able to use simple hooks such as useEffectOnce without pulling deps for other hooks such as resize-observer-polyfill for useMeasure.
Describe alternatives you've considered
It would be nice to separate each hook in a package using workspaces, it would also make it clear which hooks depend on each other through metadata. Instead of yarn add react-use I would use yarn add @react-use/use-effect-once or maybe a better naming scheme, then import useEffectOnce from '@react-use/use-effect-once'.
It might also be nice to house these hooks inside a single package, to keep import { useEffectOnce } from 'react-use' working, but that I don't know how to do without the dependency thing.
They should be defined as optional dependencies. Yarn and npm offers the --no-optional option for installing dependencies. Splitting packages would result in more node_modules folder hell.
@chapterjason I disagree on that. Scoped split packages generate a single directory under node_modules, and workspaces are very smart in avoiding duplication of dependencies. Optional dependencies have a fallback plan if they are not available, which is not the case: not having resize-observer-polyfill breaks useMeasure, thus it is not optional.
I believe splitting packages is pretty standard practice. e.g. we only use useLocalStorage and have to import the whole library... Not great. See Material UI and how they split it in the way the Op describes. Very simple process.
I would also like to see these things split up similar to https://github.com/jaredLunde/react-hook. That would allow making breaking changes in an individual hook much more manageable without having to worry about whether or not you're gonna break other hook usages. And for people who still want an all-in-one package, we should be able to have a package that pulls everything in and re-exports the things.
And now someone already squatted in the @react-use scope in npmjs.com :shrug:
What a shame, I almost used this package... but at the end I decided against it as it bundles way too many things together... (I was only interested in lifecycle hooks)
And now someone already squatted in the
@react-usescope in npmjs.com 🤷
@ranisalt How can you tell? (just curious how one can determine if a namespace has been taken on the NPM site, as that's not something I know how to do.)
FWIW, I landed here while googling for a hook to detect element resize events (i.e. useMeasure), and this was my knee-jerk reaction. Really interesting lib but I only need 1% of what it offers (for now).
A basic useMeasure implementation should only be ~20-30 lines of code. Adding 1MB of code / 500+ files to my project to get that just doesn't make sense.
Sidenote: I was going to suggest taking an approach similar to lodash, which offers single-method packages. However use of those packages is now deprecated. The rational being that as soon as you use > 1 package your bundle ends up being larger, not smaller, due to the inability to tree-shake code properly.
I'm a little unsure how I feel about that. I guess it makes sense for lodash, which is a collection of very-primitive utilities, where if you're using one you're pretty likely to need one or more of the others. But I'm not sure the same can be said of this project. It's hard to say.
Either way, as a developer, I'd love to have the option of starting out with a single, light package for my specific use case, and then decide later whether or not I want to pay the cost of installing everything.
Switch over to compiling via vite and it's easy to build multiple targets, with the esmodule version being both split (for direct imports) and tree-shakeable (for importing from the root) - I've done it on lz-string recently which is now also a pure TS project and wants similar things - have a look at the vite.config.mts file and corresponding entries in the package.json exports section!