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

reselect-map

v1.0.6

Published

Selectors for mapping over collections.

Downloads

12,419

Readme

reselect-map

npm

Selectors for mapping over collections.

Installation

npm install reselect-map reselect

Usage

This package exposes a few special selector creators. They're mostly the same as reselect's createSelector, with one major difference: the first dependency gets mapped over.

To give you a better idea, here's an example of how a selector to multiply an array of numbers would look in basic reselect and then using reselect-map.

import { createSelector } from "reselect";
import { createArraySelector } from "reselect-map";

const exampleState = {
  numbers: [1, 2, 3],
  multiplier: 5,
};

const numbers = (state) => state.numbers;
const multiplier = (state) => state.multiplier;

// reselect
const mul1 = createSelector([numbers, multiplier], (numbers, multiplier) =>
  numbers.map((n) => n * multiplier)
);

// reselect-map
const mul2 = createArraySelector(
  [numbers, multiplier],
  (number, multiplier) => number * multiplier
);

// Result: [5, 10, 15]

Notice the second version uses number instead of numbers; the result function is passed each element of numbers instead of the whole thing, and then the results are reassembled into an array.

So why would you use this? The answer is that you probably shouldn't! However, in certain situations it may significantly improve performance. Learn more in the motivation section.

API

The only thing to know is that the first dependency/selector passed is the one that gets mapped over, and all other selectors work just like they do in reselect proper. Additionally, key-based selectors like createObjectSelector and createMapSelector pass the key as the final argument.

NOTICE: This package makes use of the builtin Set and Map. If you need to support environments without Set or Map, you are going to have to polyfill it.

createArraySelector

Takes in an array, runs each element through the result function, and returns the results in a new array.

import { createArraySelector } from "reselect-map";

const exampleState = {
  numbers: [1, 2, 3],
  multiplier: 5,
};

const mul = createArraySelector(
  (state) => state.numbers,
  (state) => state.multiplier,
  (number, multiplier) => number * multiplier
);

console.log(mul(exampleState)); // [5, 10, 15]

createObjectSelector

Takes an object, runs the value at each key through the result function, and returns an object with the results. The key is passed as the last argument to the selector function.

import { createObjectSelector } from "reselect-map";

const exampleState = {
  numbers: { a: 1, b: 2 },
  multiplier: 5,
};

const mul = createObjectSelector(
  (state) => state.numbers,
  (state) => state.multiplier,
  (number, multiplier, key) => `${key}:${number * multiplier}`
);

console.log(mul(exampleState)); // { a: 'a:5', b: 'b:10' }

createListSelector

Takes anything with an array-like map function, and returns whatever that returns. This conveniently makes it compatible with Immutable js collections and similar without erasing the input type.

import { createListSelector } from "reselect-map";
import Immutable from "immutable";

const exampleState = {
  numbers: Immutable.List([1, 2, 3]),
  multiplier: 5,
};

const mul = createListSelector(
  (state) => state.numbers,
  (state) => state.multiplier,
  (number, multiplier) => number * multiplier
);

console.log(String(mul(exampleState))); // List [5, 10, 15]

createMapSelector

Like the sequence selector, but it expects the map function to provide a second argument to the callback that represents the key. This key is passed as the last argument to the selector function. This is mostly to support Immutable's Collection.Keyed types.

import { createMapSelector } from "reselect-map";
import Immutable from "immutable";

const exampleState = {
  numbers: Immutable.Map({ a: 1, b: 2 }),
  multiplier: 5,
};

const mul = createMapSelector(
  (state) => state.numbers,
  (state) => state.multiplier,
  (number, multiplier, key) => `${key}:${number * multiplier}`
);

console.log(String(mul(exampleState))); // Map { "a": "a:5", "b": "b:10" }

Need more?

I'm hoping that what I've got here covers most common use cases, but it's not difficult to expand. Please let me know if there are any other selector types you'd like, or submit a pull request!

Motivation

When doing very expensive computations on elements of a collection, reselect might not give you the granularity of caching that you need. Imagine a selector that looks like this:

import { createSelector } from "reselect";

const expensiveSelector = createSelector(
  (state) => state.largeArray,
  (largeArray) => largeArray.map(expensiveFunction)
);

Notice that every time largeArray is changed, every single element of the array will be run back through expensiveFunction. If largeArray is very large or expensiveFunction is very expensive, this could be very slow.

What would be better is if we only recomputed those elements that are new or have changed. That's what this package does. Your expensiveFunction only runs on the elements it needs to.

When shouldn't you use reselect-map

When you don't need it. If your selector takes an array and multiplies every element by five (like in all of the examples), this package will slow your code down. In situations where you're having performance issues with reselect and you're thinking about how to cache on an element level, this package is here for you.