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

@mnpenner/imut-utils

v0.1.43

Published

Immutability helper for React.

Downloads

24

Readme

imut-utils

Immutability helper for React.

Installation

yarn add @mnpenner/imut-utils
# or
npm install @mnpenner/imut-utils

Links

  • Docs: https://mnpenner.github.io/imut-utils
  • Repo: https://github.com/mnpenner/imut-utils
    • Code: https://github.com/mnpenner/imut-utils/tree/default/src
    • Issues: https://github.com/mnpenner/imut-utils/issues
  • Npm: https://www.npmjs.com/package/@mnpenner/imut-utils
  • Yarn: https://yarnpkg.com/package/@mnpenner/imut-utils
  • Bundlephobia: https://bundlephobia.com/package/@mnpenner/imut-utils
  • Unpkg: https://unpkg.com/@mnpenner/imut-utils
  • jsDelivr: https://cdn.jsdelivr.net/npm/@mnpenner/imut-utils

Quick Start

This library is designed to be paired with React, but has no such dependency. Here's an example lightly modified from a project I'm working on:

import {fpShallowMerge, fpMapSet} from '@mnpenner/imut-utils'

function App(props: AppProps) {
    const [state, setState] = useState<Map<string, SomeState>>(() => new Map)
    
    const doSomething = useCallback(async () => {
        const key = uniqId()
        
        // `fpMapSet` returns a function which takes in the previous state, clones it and sets the given key to the given value.
        setState(fpMapSet<string, SomeState>(key, {
            loading: true,
            coolFact: 'The lifespan of a single taste bud is about 10 days.',
        }))
        
        const result = await fetchSomething()
        
        // ...the value for that key can also be a function. If so, the function will be called with the current value for that key. Here, we chain that together with `fpShallowMerge` which again returns a function expecting the previous state and merges in the given state.
        setState(fpMapSet<string, SomeState>(key, fpShallowMerge({
            result,
            loading: false,
        })))
        
        // `state` will be Map([[key,{coolFact: "...", result: {...}, loading: false}]])
        // Notice how we didn't have to read the map, clone it, pull out the current key and spread it into the new object. The deeper your objects get, the more typing you save because all the functions can be chained together.
    }, [])
}

Or here's another fun one:

const [timings, setTimings] = useState<Map<string, number[]>>(() => new Map)
// ...
const startTime = Date.now()
await doSomethingThatTakesAwhile()
setTimings(fpMapSet(timingKey, fpArrayInsertSorted(Date.now() - startTime)))

Now you have a Map full of sorted arrays. And you didn't need to initialize the map either, most of the array functions will create an empty array if the current state is undefined.

Why?

There are a lot of other immutable libs for React out there. Why use this one?

Simplicity.

I'm not a fan of libs that use Proxies under the hood to track what mutations you've performed, they sometimes interfere when this is expected to be of a certain type. Why do you need an escape hatch to "get the current value for debugging purposes"? You already have it -- the callback from React's useState is always current, use it! Why do you need to opt-in to use Maps and Sets? What is this "artificial immutability"? There's no magic in imut-utils, just plain old objects. If you want to accidentally mutate it, it's your foot, not mine.

immutability-helper is pretty good, but it's a little harder extend, and you have to be comfortable with some fancy syntax. It also makes me slightly uncomfortable that there could be a key collision if I ever use an object with a property called $push.

Want to extend this lib? Just add a new function to your project, there's nothing to integrate. Most of the functions here are just a few lines, the only benefit here is that they have tests that you now don't have to write.

How big is it?

1.4 kB minified+gzipped, but it's tree-shakeable; the output is ES modules. You shouldn't pay for what you don't use when bundled.

Dependencies?

None. That's a feature.

Is it stable?

No. You should pin against a minor or patch version until this reaches 1.0. I will try to make API breaks minor bumps (until 1.0, then majors are breaks, per semver). Note that ^ does exactly this, so you probably don't have to do anything.

Or just copy the functions you like out of the src. If you prefer JS and don't want to build this package yourself, just copy from Unpkg.

Naming

fp stands for "functional programming" or something. I couldn't come up with a good name for "function that returns a function that expects the previous state as input" so I just copied the naming from lodash/fp. It's basically what React's SetStateAction<S> (returned by useState) accepts.

Contributions

Open a ticket and we'll talk.

License

MIT