Git Product home page Git Product logo

re-reselect's People

Contributors

alexdlm avatar andarist avatar andersdjohnson avatar dante-101 avatar dependabot[bot] avatar julius-retzer avatar lukyth avatar markbrinkman avatar mechmillan avatar olslash avatar renovate-bot avatar renovate[bot] avatar rufman avatar sgrishchenko avatar stevemao avatar suark avatar toomuchdesign avatar tracykm avatar xsburg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

re-reselect's Issues

include key resolvers

Is there a way to include key resolvers, for example, the way I use re-reselect is like this:

const filterByPrecedence = createCachedSelector(
    getProps("documentTypes", "precedenceTitle"),
    (documentTypes, precedenceTitle) =>{
        return documentTypes.filter(({ precedence }) => precedence && precedence.title === precedenceTitle)
    }
)(processCacheName("documentTypes", "precedenceTitle"));

in this case I take data from state and I also process the documentTypes array as string because if a new reference of the array goes to the store, the selector is recomputed.

I would like to know your opion about this.

Cache size

Should we be able to specify a cache size? There's nothing stopping the cache from growing infinitely, short of calling clearCache(), but a cache size might be a nicer way to guard against it.

A typo in README

There is a typo in README.md:

Call selector with with provided arguments

Return default cache key selector when not defined

This is more a question than an issue.

I am wondering what is the best practice when my cache-key is not defined.

In my case, I use a selector argument as the cache-key, but this one can be undefined or null at a given time.

  • Should I return other value ?
  • What would be the behavior if I return empty string '' ?

E.g.

// Selector
const getUserById = createCachedSelector(mySelectorFn)((state, { userId }) => userId) // Use the user id as cache key

// In my component
// In some case, I render some components before my store has been hydrated
// Resulting in userId=undefined
const user = useSelector(state => getUserById(state, { userId }) // undefined

Documentation lacks any reference to `createStructuredSelector`

Do you want to request a feature or report a bug?

No.

What is the current behavior?

Re-reselect's documentation does not reference reselect's createStructuredSelector and therefore it is not clear whether there is an equivalent function in re-reselect, e.g., createCachedStructuredSelector, or if there is some other recommended way to convert existing reselect structuredSelectors to re-reselect selectors, or if it is merely a "convenience" feature of reselect not requiring the explicit support of re-reselect.

What is the expected behavior?

Unknown. Documentation should show an example of how this libraries authors' intend structuredSelectors to be converted to re-reselect structuredSelectors.

Steps to Reproduce the Problem

Read documentation.

Specifications

  • Version: latest
  • Platform: n/a
  • Subsystem: n/a

Discussions on the project

Hi @toomuchdesign

Thanks again for pinging me about re-reselect on SO.

I have implemented it in my app super easily.

I have a few points I'd be happy to discuss with you though (sorry I removed you issue layout):

  • the syntax is createCachedSelector(regularSelector)(keySelector). I'd find it more natural if it were createCachedSelector(keySelector)(regularSelector) as createCachedSelector(keySelector) would become the smarter createSelector from reselect. What do you think? I know this would be a breaking change so it might not be possible in a near future, but at least it would have been discussed. ๐Ÿ˜„

  • the keySelector syntax is (state, otherParams) => {}. But I reckon I never used the state params here. Isn't the selector supposed to be recalculated if the state changes, hence it shouldn't be part of the key parameters, should it? Hence, shouldn't it be instead:

createCachedSelector(
  (state, id) => state.data.collection,
  (state, id) => id,
  (collection, id) => collection.find(c => c.id === id)
)(id => id)
  • finally I have cases where the selector doesn't hang on any extra parameter. For now, the syntax I have been using is:
export default createCachedSelector(
  state => state.data.collection,
  collection => collection
)(() => '')

Shouldn't this be default? If I remove the () => '', I get an error. I know I could use the regular reselect createSelector method, but to uniformize my code, I'd rather user re-reselect everywhere.

Dropped support for createCachedSelector calls with multiple arguments?

Do you want to request a feature or report a bug?

Question

What is the current behaviour?

Why was the support for calling createCachedSelector() with multiple arguments dropped and what exactly does this mean?

What is the expected behaviour?

N/A

Steps to Reproduce the Problem

N/A

Specifications

N/A

Selector recomputes every time

Do you want to request a feature or report a bug?

It's more of a question on usage and clarification what i'm doing wrong. Depending on what is really happening, it might be a bug, but more likely just some additions to README.

What is the current behaviour?

When using re-reselect with redux the selectors always recompute. I'm able to make simplified examples work, but when integrated into a more complex scenario, caching breaks.

I made a demo here: https://codesandbox.io/s/pmmry9j70m
If you click the "Select this article" button on the same item multiple times, the selector is recalculated.

Some background:
The buttons dispatch a thunk action that sets the selectedArticle โ€“ an object of multiple ids โ€“ in the state. This object is then retrieved in the connected 'App.js' and fed as props into the getArticle selector.

My current hypothesis is that the selectors recompute due to the state change in selectedArticle.

What is the expected behaviour?

If you click the "Select this article" button on the same item multiple times, the selector should be pulled from cache, as the return value of the key resolver function did not change.

Steps to Reproduce the Problem

  1. Go to https://codesandbox.io/s/pmmry9j70m
  2. Click the "Select this article" button multiple times on the same button
  3. See the recomputations count rise

(If the buttons don't work, you may have to reload the sandbox)

Specifications

  • Version: 2.1.0
  • Platform: -
  • Subsystem: -

Invalidate reselect cache only if resolverFunction is changed

In the docs example is mentioned a code passing the state object in the first argument:

const getPieceOfData = createCachedSelector(
  state => state,
  (state, itemId) => itemId,
  (state, itemId, dataType) => dataType,
  (state, itemId, dataType, otherArg) => otherArg,
  (state, itemId, dataType, otherArg) => expensiveComputation(state, itemId, dataType, otherArg),
)(
  (state, itemId, dataType) => dataType,    // Memoize by dataType
);

Unfortunatly I couldn't reproduce this behavior and created a little test example.
It assumes we are using immutable js

const mySelector = createCachedSelector(
  state => state, 
  state => state.foo,
  state => state.bar, 
  (state, foo, bar) => {
    console.log('called');

    return foo + bar;
})(state => 'justString');

// Selector is called when the state is changed only 
// But if the state is changed it means it's a new object.
const res = mySelector({foo: 'foo', bar: 'bar'})

The selector function is not cached here and console.log always logs logged. Do I do anything wrong? or maybe it is impossible without custom cacheCreator?

Add a possibility to delete all reselect selectors stored in the cache under a specific key pattern

Hi,

I have a problem with the way we can remove selectors from a cache object.

For example, in my code, the keys under which my selectors are stored, are generated using a function and are following a specific pattern (number(:number)*). I would like to remove from the cache every selector stored under a key starting with a "1".
The problem is, that I cannot use selector.getMatchingSelector because it uses the resolver instead of directly checking if _cache has a selector stored under a specific string.

I found a way to counter that by adding this function to the createCachedSelector function:

selector.getCache = () => {
      return cache._cache;
};

and by removing manually in my code every selector stored under a key starting with a "1".
But it would be much cleaner if something similar was implemented directly in your cache objects.

So my question is the next, would it be possible to add a function which removes all the selectors of a cache object that are stored under a specific key pattern ?
If not, could you at least add a function to createCachedSelector which allows us to get the _cache of a cache object (like the one I had to add).

Feel free to let me know, if I'm not being clear enough !

Debugging cache

Hi @toomuchdesign, thank you for creating this library! I was wondering if there are any recommendations around debugging selectors to make sure that the cache is working, and to see what might be causing changes?

I came across https://github.com/kbrownlees/reselect-change-memoize and was wondering if you've considered a similar utility for re-reselect which provides callback when new objects are added to cache or when something is used from cache?

Any way to pass a custom equalityCheck?

First off, I love this library!

I have a case where I need to pass a custom equalityCheck (performing a shallow check on an array vs the default reference check). The problem that I'm facing is that when composing my re-reselect with a reselect selector that performs the custom equalityCheck, I lose all of the performance benefits of re-reselect in the first place (as the reselect selector has a cache size of 1). Example:

// Custom equality check function
const shallowArrayEqualityCheck = (currentVal, previousVal) => {
    if (currentVal.length !== previousVal.length) {
        return false
    }

    const length = currentVal.length
    for (let i = 0; i < length; i++) {
        if (currentVal[i] !== previousVal[i]) {
            return false
        }
    }

    return true
}

// Selector creator that uses my custom equalityCheck function
const createShallowEqualSelector = createSelectorCreator(
    defaultMemoize,
    shallowArrayEqualityCheck,
)

// Using the selector creator to fetch messages and memoize correctly (using shallow check)
const messagesSelector = createShallowEqualSelector(
    (state, chatroomId) => state.chatrooms[chatroomId].messages.map(messageId => getMessage(state, messageId)),
    messages => messages,
)

// Use cached selector to cache based on chatroom
const messagesCachedSelector = createCachedSelector(
    messagesSelector,
    messages => messages,
)(
    (state, chatroomId) => chatroomId,
)

Ultimately, I wish that I could pass in an equalityCheck to the cached selector, which would remove this issue!

Any thoughts/tips/ideas would be much appreciated!

[typings] OutputCachedSelector and OutputParametricCachedSelector do not include selectorCreator

Hi, and thanks for this handy library.

It looks like the selectorCreator parameter is missing from the typings.

API Documentation:

reReselect([reselect's createSelector arguments])(resolverFunction, selectorCreator = selectorCreator)

(This should maybe be replaced with createCachedSelector in the doc to avoid confusion)

Typing:

export default function createCachedSelector<S, R1, T> (
  selector: Selector<S, R1>,
  combiner: (res: R1) => T
): OutputCachedSelector<S, T, (res: R1) => T>;

export type OutputCachedSelector<S, R, C> = (resolver: Resolver<S>) => OutputSelector<S, R, C> & {
  getMatchingSelector: (state: S, ...args: any[]) => OutputSelector<S, R, C>;
  removeMatchingSelector: (state: S, ...args: any[]) => void;
  clearCache: () => void;
  resultFunc: C;
};

Thanks again, and tell me if I am missing something.

Not being passed resolved arguments to resolver function

import createCachedSelector from 're-reselect';
import { createSelector } from 'reselect';
import { orderBy } from 'lodash/collection';

const entitiesSelector = createSelector(
  selectGlobal,
  (state) => state.get('entities')
);

const pathArgSelector = (state, { path }) => path;

const entitiesPathSelector = createSelector(
  entitiesSelector,
  pathArgSelector,
  (entities, path) => entities.get(path)
);

const sortBySelector = (state, { sortBy }) => sortBy;
const sortOrderSelector = (state, { sortOrder }) => sortOrder;

const entitiesSortedSelector = createCachedSelector(
  entitiesPathSelector,
  sortBySelector,
  sortOrderSelector,
  (entities, sortBy, sortOrder) => {
    const cacheKey = `${entities.hashCode()}:${sortBy}:${sortOrder}`;
    console.log('resolver', cacheKey); //  resolver -181045611:id:desc
    console.log('no cache for ', sortBy, sortOrder); //  no cache for  id desc
    return orderBy(entities.toList().toJS(), getSortIteratee(sortBy), sortOrder);
  }
)((entities, { sortBy, sortOrder }) => { 
  // NOTE here I'm actually getting passed my original state object! 
  const cacheKey = `${entities.hashCode()}:${sortBy}:${sortOrder}`;
  console.log('cached selector', cacheKey);  // cached selector 403733751:id:desc
  return cacheKey;
})

Called like so in container.

const mapStateToProps = (state, props) => ({
  entities: entitiesSortedSelector(state, {
    path: props.entities, // ~ 'posts' 
    sortBy: props.sortBy || EntityQuery.defaultProps.sortBy,
    sortOrder: props.sortOrder || EntityQuery.defaultProps.sortOrder,
  }),
});

Provide an example showing composition from dissimilar selectors/different slices of state

First off, this lib has breathed fresh air into my app. I am functional programming nube, so I tend to stumble through over-simplified examples. I have some simple, cached selectors wired up by following the examples in your docs. They look like this:

const getAllData = state => state.sliceX;
const getSliceXByID = createCachedSelector(
    getAllData,
    (state, sliceXid)=> sliceXid,
    (allData, sliceXid) => {
        ...get stuff from allData using slice X ID
    }
)(
    (state, sliceXid) => sliceXid
)

On one particular nasty view, I need to merge, transform, and aggregate two slices of state. Each slice has a selector with the calling convention above--that works well elsewhere in the app: getSliceXByID( xID ) and getSliceYByID( yID). I can't wrap my brain around the syntax of composing a new selector from these two. The existing example that shows the re-reselect version of the reselect visibility derive data from the same slice of state keyed by the same id. I need something showing disparate state slices:

const getExpensiveMorphation = createCachedSelector(
   getSliceXByID,
   getSliceYByID,
   {..I get lost in the weeds here}
)(
   (state, sliceXid, sliceYid) =>...computed compound key of X and Y id. (this part I understand).
)

I notice the array [] input in the example and suspect that I need to keep that in play.

getMatchingSelector can return OutputParametricSelector

In the typescript definitions, line 29, getMatchingSelector: (state: S, ...args: any[]) returns ParametricSelector<S, P, R>;

My tests (which are passing successfully) are expecting an OutputParametricSelector with recomputations and resetcomputations functions on them. It will be great to change the definition to

getMatchingSelector: (state: S, ...args: any[]) => OutputParametricSelector<S, P, R, any>;

Using any is not the best solution but it definitely is better than using ParametricSelector

Boolean cannot be memorized

const getSelectedCls = createCachedSelector(
    props => props.a === props.b,
    bol => {
        // Do what I want to do
    }
)(
    props => props.a === props.b
)
getSelectedCls(props); // There is no work

`recomputations` property for testing

Great lib -- seems like it should address a pain point in my app nicely.

like what's mentioned in https://github.com/reactjs/reselect#q-how-do-i-test-a-selector, i'd like to be able to test that my cached selectors are working like I expect.

given the example code from the readme:

const cachedSelector = createCachedSelector(
    (A, B, someArg) => expensiveComputation(A, B, someArg}),
)(
    (state, someArg) => someArg,
);

const fooSelector = cachedSelector(state, 'foo');
const barSelector = cachedSelector(state, 'bar');

I guess the API could look like:

  cachedSelector.recomputations(state, 'foo')

What do you think?

selectorCreator typing issue with reselect >= 4.1.0

What is the current behaviour?

The current typing for CreateSelectorInstance is:
export type CreateSelectorInstance = typeof createSelector;

reselect from 4.1.0 has changed the type as the defaultMemoized createSelector adds a clearCache() (not to be confused with re-reselect's createCachedSelector(...).clearCache()). However custom selectors via reselect's createSelectorCreator, or even just custom selectors without using reselect don't necessarily have this method.

What is the expected behaviour?

selectorCreator type shouldn't be tied to reselect's createSelector type, or be more lenient.

Steps to Reproduce the Problem

  1. Bump reselect to 4.1.0+
createCachedSelector(
    (state) => state.foo,
    (state, id) =>id,
    (foo, id) => foo[id],
    {
        keySelector: (foo, id) => id, 
        selectorCreator: createSelectorCreator((func) => func),
    }
  1. Observe type error on selectorCreator key: Property 'clearCache' is missing in type '((state: {}) => any) & OutputSelectorFields<(...args: any[]) => any> & { readonly length: number; [Symbol.hasInstance]: (value: any) => boolean; toString: () => string; ... 6 more ...; caller: Function; }' but required in type '{ clearCache: () => void; }'.ts(2322)

Specifications

  • Version: 4.0.0
  • Typescript version: 4.6.4

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Awaiting Schedule

These updates are awaiting their schedule. Click on a checkbox to get an update now.

  • chore(deps): update dependency lint-staged to ^15.2.5
  • chore(deps): update dependency rimraf to ^5.0.7
  • chore(deps): update dependency ts-jest to ^29.1.3
  • chore(deps): update update babel packages to ^7.24.6 (@babel/core, @babel/preset-env)
  • chore(deps): update dependency rollup to ^4.18.0

Detected dependencies

github-actions
.github/workflows/ci.yml
  • actions/checkout v4
  • actions/setup-node v4
npm
package.json
  • @babel/core ^7.24.4
  • @babel/preset-env ^7.24.4
  • @rollup/plugin-babel ^6.0.4
  • @types/jest ^29.5.12
  • all-contributors-cli ^6.26.1
  • babel-jest ^29.7.0
  • jest ^29.7.0
  • lint-staged ^15.2.2
  • prettier ^3.2.5
  • reselect ^5.1.0
  • rimraf ^5.0.5
  • rollup ^4.17.2
  • rollup-plugin-copy ^3.5.0
  • simple-git-hooks ^2.11.1
  • ts-jest ^29.1.2
  • typescript ^5.4.5
  • reselect ^5.0.0
nvm
.nvmrc
  • node 20

  • Check this box to trigger a request for Renovate to run again on this repository

Evaluate option to provide `keySelector` with same args as `resultFunc`

A lot of users stumbled upon the question of which arguments are actually provided to keySelector function.

Currently they receive the same arguments as the inputSelectors and the selector itself, but it's easy to mistakenly think that they receive same arguments as resultFunc (which are the result of inputSelectors), instead.

See these threads:

Given that this problem could be alleviated with a better documentation, I'd like to better understand pros and cons of adding an option to provide keySelectors with resultFunc results as proposed here by @mbellman.

Documentation request

I'd like to use object as a param of a selector

I found this page and looks like what I need link But I can't seem to be able to get it to work.

const keySelector = (state, params) => JSON.stringify(params)

const selectData = createCachedSelector(
  selectState,
  (data, params) => params, // params is an object
  (data, params) => {
    const result = something // compute
    return result
  },
)({
  keySelector,
  cacheObject: new LruObjectCache({ cacheSize: 5 }),
})

I also tried

const selectData = createCachedSelector(
  selectState,
  (datae, params) => params,
  (data, params) => {
    const result = something // compute
    return result
  },
)((state, params) => JSON.stringify(params))

Both of the above are recomputing each time. What am I missing?

Can you please provide an example in the documentation?

Many thanks!

Unable to get this to cache anything

This library appears to be exactly what we need, but I can't get it to cache a thing. I'd love to know what I'm doing wrong as I'm pretty sure I've followed the docs correctly.

Container

const mapStateToProps = (state, props) => ({
  pagedEntities: entitiesPagedSelector(state, {
    path: props.entities,
    perPage: props.perPage || EntityQuery.defaultProps.perPage,
    currentPage: props.currentPage || EntityQuery.defaultProps.currentPage,
    sortBy: props.sortBy || EntityQuery.defaultProps.sortBy,
    sortOrder: props.sortOrder || EntityQuery.defaultProps.sortOrder,
  }),
});

function mapDispatchToProps(dispatch, props) {
  return {
    componentWillMount: () => {
      dispatch(loadEntitiesIfNeeded(props.entities));
    },
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(EntityQuery);

Selectors

const entitiesPathSelector = (state, { path }) =>
  state.getIn(['global', 'entities', path]);

const entitiesListSelector = createCachedSelector(
  entitiesPathSelector,
  pathArgSelector,
  (entities, { path }) => {
    console.log('no cache for entitiesListSelector', path)
    return entities.toList()
  }
)((entities, { path }) => {
  console.log('entitiesListSelector cache is:', path);
  return path;
});

const entitiesArraySelector = createCachedSelector(
  entitiesListSelector,
  pathArgSelector,
  (entitiesList, { path }) => {
    console.log('no cache for entitiesArraySelector', path);
    return entitiesList.toJS();
  }
)((_, { path }) => {
  console.log('entitiesArraySelector cache is:', path);
  return path;
});

const entitiesSortedSelector = createCachedSelector(
  entitiesArraySelector,
  sortBySelector,
  (entities, { sortBy, sortOrder }) => {
    console.log('no cache for entitiesSortedSelector', sortBy, sortOrder);
    return orderBy(entities, getSortIteratee(sortBy), sortOrder);
  }
)((entities, { path, sortBy, sortOrder }) => {
  console.log('entitiesSortedSelector cache is: ', path, sortBy, sortOrder);
  return `${path}${sortBy}${sortOrder}`
});

const entitiesPagedSelector = createCachedSelector(
  entitiesSortedSelector,
  pagingSelector,
  (entities, { currentPage, perPage }) => {
    const length = entities.length;
    const totalPages = Math.ceil(Math.max(length, 0) / perPage);
    const pageNum = Math.min(currentPage, totalPages);
    const offset = (pageNum - 1) * perPage;
    const end = offset + perPage;
    const haveNextPage = end < entities.length;
    const havePrevPage = pageNum > 1;
    const page = slice(entities, offset, end);
    console.log('no cache for pagedSelector ' + offset);
    return {
      page,
      havePrevPage,
      haveNextPage,
      totalPages,
      currentPage,
      perPage,
    };
  }
)((entities, { path, perPage, currentPage, sortBy, sortOrder }) => {
  //console.log(entities) // also this is a Map here but an array above !!
  const cache = `${path}:${perPage}:${currentPage}`;
  console.log('pagedSelector cache is: ', cache);
  return cache
});

Nothing caching

rereselect

Selectors inside a resolver, as args alone might not be enough to key

Hey I've posted two dumb issues today, lets go for three. ;)

Is this on the right track?

const entitiesSortedSelector = createCachedSelector(
  entitiesPathSelector,
  sortBySelector,
  sortOrderSelector,
  (entities, sortBy, sortOrder) =>  
     orderBy(entities.toList().toJS(), getSortIteratee(sortBy), sortOrder);
)((state, { path, sortBy, sortOrder }) => {
  const entities = entitiesPathSelector(state, { path }); 
  return `${entities.hashCode()}:${sortBy}:${sortOrder}`;
});

I initially hoped that the resolver function would recieve the same args as the resolved function ( issue #2), if it doesn't then I really want to check that I'm dealing with the same entities collection here ( path param alone isn't enough )

Is the code above a correct path to take ?

Large cacheKey's not setting?

I noticed a huge performance hit in my project and tracked it down to a createCachedSelector that was constantly re-evaluating.

This createCachedSelector is unique to my other well behaving selectors in that it uses a generated cacheKey from another selector.

((state, props) => {
    const token = selectEntityItemAssetNamesToken(state, props);
    return token;
  });

The token that returns is a base64 hash string. here is an example:

"bWVjaHNuaXBlci1oYW5kcy1IZWFkLW1lY2hzbmlwZXItaGFuZHMtQ2hlc3QtbWVjaHNuaXBlci1oYW5kcy1Db3JlLW1lY2hzbmlwZXItaGFuZHMtV2Fpc3QtbWVjaHNuaXBlci1oYW5kcy1TaG91bGRlckwtbWVjaHNuaXBlci1oYW5kcy1CaWNlcEwtbWVjaHNuaXBlci1oYW5kcy1Bcm1MLW1lY2hzbmlwZXItaGFuZHMtSGFuZEwtbWVjaHNuaXBlci1oYW5kcy1TaG91bGRlclItbWVjaHNuaXBlci1oYW5kcy1CaWNlcFItbWVjaHNuaXBlci1oYW5kcy1Bcm1SLW1lY2hzbmlwZXItaGFuZHMtSGFuZFItbWVjaHNuaXBlci1oYW5kcy1UaGlnaEwtbWVjaHNuaXBlci1oYW5kcy1TaGluTC1tZWNoc25pcGVyLWhhbmRzLUZvb3RMLW1lY2hzbmlwZXItaGFuZHMtVGhpZ2hSLW1lY2hzbmlwZXItaGFuZHMtU2hpblItbWVjaHNuaXBlci1oYW5kcy1Gb290Ui1tZWNoc25pcGVyLWhhbmRzLUJhY2tQYWNr"

I've confirmed that these tokens are constants and not mutating.

If I change this selector to return a smaller key it caches correctly and does not re evaluate.

((state, props) => {
    return props.entityId;
  });

further more I can reproduce the issue with a static token like:

((state, props) => {
    const token = "bWVjaHNuaXBlci1oYW5kcy1IZWFkLW1lY2hzbmlwZXItaGFuZHMtQ2hlc3QtbWVjaHNuaXBlci1oYW5kcy1Db3JlLW1lY2hzbmlwZXItaGFuZHMtV2Fpc3QtbWVjaHNuaXBlci1oYW5kcy1TaG91bGRlckwtbWVjaHNuaXBlci1oYW5kcy1CaWNlcEwtbWVjaHNuaXBlci1oYW5kcy1Bcm1MLW1lY2hzbmlwZXItaGFuZHMtSGFuZEwtbWVjaHNuaXBlci1oYW5kcy1TaG91bGRlclItbWVjaHNuaXBlci1oYW5kcy1CaWNlcFItbWVjaHNuaXBlci1oYW5kcy1Bcm1SLW1lY2hzbmlwZXItaGFuZHMtSGFuZFItbWVjaHNuaXBlci1oYW5kcy1UaGlnaEwtbWVjaHNuaXBlci1oYW5kcy1TaGluTC1tZWNoc25pcGVyLWhhbmRzLUZvb3RMLW1lY2hzbmlwZXItaGFuZHMtVGhpZ2hSLW1lY2hzbmlwZXItaGFuZHMtU2hpblItbWVjaHNuaXBlci1oYW5kcy1Gb290Ui1tZWNoc25pcGVyLWhhbmRzLUJhY2tQYWNr";
    return token;
  });

Null cache key automatically returns undefined

Do you want to request a feature or report a bug?

Not so much a bug as an unexpected behavior.

What is the actual behavior?

Using the default cache strategy, calling a selector with arguments that result in a null cache key will cause the selector to short-circuit and return undefined, totally circumventing the actual selector code. A warning is printed to the console noting that null is an invalid cache key.

What is the expected behaviour?

I would expect to be able to handle a null value in the body of my selector, but I can't. This is particularly pernicious when I'm already returning non-undefined default values (e.g. an empty list) in error cases and assuming the default value's properties (e.g. calling map on the result of the selector function).

Steps to Reproduce the Problem

Example code:

const getCollectionById = createCachedSelector(
  state => state.collections,
  (state, collectionId) => collectionId,
  (collections, collectionId) => collections[collectionId] || []
)((state, collectionId) => collectionId);
// ...
// state is { collections: { a: ['thing1', 'thing2'] } }
const yellCollection = id => getCollectionById(state, id).map(thing => thing.toUpperCase());
const yelledB = yellCollection("b"); // expect [], but get an error for trying to map undefined

Possible solutions

  • Allow a default value as an option when cache keys are 'malformed' (at the selector level, not the strategy level)
  • Just execute the selector anyway when cache keys are 'malformed'
  • Let null be an eligible cache key in the default cache strategy (it's a little icky, but it does work)

Typescript: isValidCacheKey() expects 0 arguments

Do you want to request a feature or report a bug?

bug

What is the current behaviour?

TS typings for isValidCacheKey should take an argument

What is the expected behaviour?

isValidCacheKey('string') should not give a type error

Steps to Reproduce the Problem

import createCachedSelector from 're-reselect';

type State = {
    id: string,
    thing: string
}

const baseSelector = (state: State) => state;
const resolver = (state: State) => state.id

const cachedSelector = createCachedSelector(baseSelector, (state) => state.thing)(resolver);

cachedSelector({
    id: '1',
    thing: 'thing1'
})

const cache = cachedSelector.cache;

cache.isValidCacheKey('1') // Type Error: Expected 0 arguments but got 1;

Specifications

  • Version: 2.1.0

[suggestion] More explicit example of multiple inputs to set the cache key

I lost some time figuring out that the resolverFunction can return a string and allow this:

createCachedSelector(
  ...
)((state, props) => `${props.arg1}:${props.arg2}`)

I even wrote a patch to allow the resolverFunction to return an array before realizing this, and feeling dumb...

It would be nice to have an example illustrating this case in the documentation :)

Typescript: Selector type does not handle additional arguments

Do you want to request a feature or report a bug?

bug

What is the current behaviour?

Passing types to the example with multiple arguments from the docs leads to type errors.

What is the expected behaviour?

No type errors.

Steps to Reproduce the Problem

Assign ts types to createCachedSelector, like:

const getPieceOfData = createCachedSelector<StateType, StateType, ItemIdType, DataTypeType, CombinerReturnType>(
  state => state, // selector1: ok
  (state, itemId) => itemId, // selector2: is not assignable to type Selector because it has more than one argument.
  (state, itemId, dataType) => dataType, // selector3: same issue as selector2
  (state, itemId, dataType) => expensiveComputation(state, itemId, dataType)
)(
  (state, itemId, dataType) => dataType // Use dataType as cacheKey
);

Manually changing the Selector type from
export type Selector<S, R> = (state: S) => R;
to
export type Selector<S, R> = (state: S ,...args: any[]) => R;
would fix the issue.

type inference on createStructuredCachedSelector?

Do you want to request a feature or report a bug?

Maybe a bug?

What is the current behaviour?

Type error when calling createStructuredCachedSelector without type parameters:

Typescript fails to infer the type parameters:

const state = { a: 1, b: "asdf " };
type State = typeof state;

const mySelectorA = (state: State) => state.a;
const mySelectorB = (state: State) => state.b;

const structuredSelector = createStructuredCachedSelector({
  x: mySelectorA,
  y: mySelectorB,
})((s: State) => "asdf");
/*
No overload matches this call.
  Overload 2 of 2, '(selectors: { x: ParametricSelector<unknown, unknown, number>; y: ParametricSelector<unknown, unknown, string>; }): OutputParametricCachedSelector<unknown, unknown, { x: number; y: string; }, (...args: (string | number)[]) => { x: number; y: string; }, ParametricSelector<unknown, unknown, string | number>[]>', gave the following error.
    Type '(state: { a: number; b: string; }) => number' is not assignable to type 'ParametricSelector<unknown, unknown, number>'.
      Types of parameters 'state' and 'state' are incompatible.
        Type 'unknown' is not assignable to type '{ a: number; b: string; }'.
  Overload 2 of 2, '(selectors: { x: ParametricSelector<unknown, unknown, number>; y: ParametricSelector<unknown, unknown, string>; }): OutputParametricCachedSelector<unknown, unknown, { x: number; y: string; }, (...args: (string | number)[]) => { x: number; y: string; }, ParametricSelector<unknown, unknown, string | number>[]>', gave the following error.
    Type '(state: { a: number; b: string; }) => string' is not assignable to type 'ParametricSelector<unknown, unknown, string>'.
      Types of parameters 'state' and 'state' are incompatible.
        Type 'unknown' is not assignable to type '{ a: number; b: string; }'.
*/

Specifying the type parameters explicitly works:

const state = { a: 1, b: "asdf " };
type State = typeof state;

const mySelectorA = (state: State) => state.a;
const mySelectorB = (state: State) => state.b;

const structuredSelector = createStructuredCachedSelector<
  State,
  { x: ReturnType<typeof mySelectorA>; y: ReturnType<typeof mySelectorB> }
>({
  x: mySelectorA,
  y: mySelectorB,
})((s: State) => "asdf");

What is the expected behaviour?

Are the type parameters supposed to be inferred or explicitly defined? createCachedSelector infers the type parameters so I'm not sure if this is a bug or not, and the documentation doesn't clarify this.

Resolver function does not receive same arguments as the final selector function

Do you want to request a feature or report a bug?

I am reporting a bug.

What is the current behaviour?

createCachedSelector resolver function does not receive same arguments as the final selector function.

What is the expected behaviour?

createCachedSelector resolver function should receive same arguments as the final selector function.

Steps to Reproduce the Problem

Check the example in here: https://codesandbox.io/s/w06x9moxnk

Typo in the README

Nothing serious here, there is a small copy/pasta fail in the README, in the How do I test a re-reselect selector? paragraph.

export const getMyData = createCachedSelector(
  selectorA,
  selectorB,
  (A, B) => doSomethingWith(A, B),
)(
  (state, arg1) => arg1,   // Use arg2 as cache key
);

Can't use options `memoize` and `memoizeOptions`

Do you want to request a feature or report a bug?

A bug.

What is the current behaviour?

It is not possible to pass an options object to createCachedSelector as you can with createSelector.

I currently use createSelector with following options:

 {
    memoize: lruMemoize,
    memoizeOptions: {
      equalityCheck: (a: unknown, b: unknown) => {
        if (typeof a === 'function' && typeof b === 'function') {
          return true;
        }

        return referenceEqualityCheck(a, b);
      }
    }
  }

What is the expected behaviour?

I can pass an options object to createCachedSelector just as with createSelector.

Steps to Reproduce the Problem

The following is not possible:

createCachedSelector(...selectors, 
  // This argument causes a Typescript and runtime error
  {
  memoize: lruMemoize,
  memoizeOptions: {
    equalityCheck: (a: unknown, b: unknown) => {
      if (typeof a === 'function' && typeof b === 'function') {
        return true;
      }

      return referenceEqualityCheck(a, b);
    },
  },
  }
)((input) => input.cacheKey);

Specifications

  • Version: 5.0.0
  • Platform: Electron with Node integration
  • Subsystem:

[Feature request] Typescript typings

This is a nice little library! It would be awesome if someone who knows enough typescript could add a typings file for typescript users. I have some interest in trying it out in my Angular/ngrx project, but that would work more smoothly if typings were available.

Some examples?

Hi,

This seems great, but for the slow among us, some examples in the documentation would be nice:

  • The ways of calling a cachedSelector without getMatchingSelector if that's possible
  • How to use the cachedSelector in the FAQ example
  • How to use cachedSelectors as arguments to other selectors
  • If you connect a cachedSelector to state in one place (like mapStateToProps) and then want to specify the cacheKey later (in a component or something), how do you do that?

Thanks so much!

Key unique per selector or app

Do I need to ensure that the cache key is unique for a selector, or for the whole application ?

Seems to be per selector, so I could create two keys that are the same for different selectors I think ...

Can selector functions be used to populate variables in the cacheKey?

I'd like to set the cacheKey using not only the input args, but also using selector functions. I can't find any way to do that. Trying to use anything besides input args seems to result in undefined

Sorry this question isn't very well formed. I find this library amazing, but I have trouble conceptualizing about it after using it only twice several months ago.

Component with in re-sizable is not getting displayed

Component is not getting displayed which is written in side component

            <Resizable
                    defaultSize={{
                        width: 'auto',
                        height: 'auto',
                    }}
                    className="resizable-component"
                >
                    <AceEditor
                        width="100%"
                        height="100%"
                        mode="html"
                        theme="monokai"
                        id={id}
                        value={typeof value === 'undefined' ? '' : value}
                        placeholder={placeholder}
                        readOnly={false}
                        focus={autofocus}
                        onBlur={
                            onBlur && (event => onBlur(id, event.target.value))
                        }
                        onFocus={
                            onFocus &&
                            (event => onFocus(id, event.target.value))
                        }
                        onChange={_onChange}
                        wrapEnabled={true}
                        fontSize={14}
                        showPrintMargin={true}
                        showGutter={true}
                        maxLines={400}
                        minLines={8}
                        highlightActiveLine={true}
                        setOptions={{
                            enableBasicAutocompletion: true,
                            enableLiveAutocompletion: true,
                            enableSnippets: false,
                            showLineNumbers: true,
                            tabSize: 2,
                        }}
                    />
                </Resizable>

I need to resize once to get Ace editor display.

Documentation Mistake?

I'm probably misunderstanding, but it seems like what the readme example calls argument 2 is really argument 3?

In this example the second argument of the selector is used as cache key.

Wouldn't the second argument to the generated selector here be B though, and not someArg?


const cachedSelector = createCachedSelector(
    // Set up your Reselect selector as normal:

    // reselect inputSelectors:
    selectorA,
    selectorB,
    (state, someArg) => someArg,

    // reselect resultFunc:
    (A, B, someArg) => expensiveComputation(A, B, someArg),
)(
    /*
     * Now it comes the re-reselect caching part:
     * declare a resolver function, used as mapping cache key.
     * It takes the same arguments as the generated selector
     * and must return a string or number (the cache key).
     *
     * A new selector will be cached for each different returned key
     *
     * In this example the second argument of the selector is used as cache key
     */
    (state, someArg) => someArg,
);

In TS, import and require syntax give difference behaviors

Do you want to request a feature or report a bug?

Bug
...

What is the current behaviour?

In TS, import and require syntax give difference behaviors
...

What is the expected behaviour?

both syntax should function the same or at least it should be better with import syntax
...

Steps to Reproduce the Problem

  1. define this:
const selectObjectByCommands = createCachedSelector(
	(state: any) => state.array,
	(array: any[]) => array,
)({
	keySelector: (_state: any, commandNames: string[]) => {
		return commandNames.join('_') : '';
	},
	selectorCreator: createShallowObjectEqualSelector,
});

let commandNames: string[] = ['text1', 'text2', 'text3'];
  1. const { createCachedSelector } = require('re-reselect');
    selectObjectByCommands({ array: output }, commandNames);

Things work.

  1. import { createCachedSelector } from 're-reselect';
    selectObjectByCommands({ array: output }, commandNames);

The function call becomes not valid and got complaint :
Expected 1 arguments, but got 2.
If called with:
selectObjectByCommands({ array: output });
Program crashes.

Specifications

  • Version: 4.0.1
  • Platform: Linux
  • Subsystem: Manjaro

Use global.Reselect instead of global.reselect

Error:

Uncaught TypeError: Cannot read property 'createSelector' of undefined
at dist/index.js:26

'reselect' is added as window.Reselect. But re-reselect gets 'reselect' by window.reselect.

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Error type: Cannot find preset's package (github>whitesource/merge-confidence:beta)

`unexpected argument error` type error when `createStructuredCachedSelector` provided with 2+ arguments

Do you want to request a feature or report a bug?

bug

What is the current behaviour?

When a selectors of a structured cached selector has an optional argument, typescript gives "unexpected argument error" when the structured cached selector is called with that optional argument.

What is the expected behaviour?

TypeScript should not give error (I think)

Steps to Reproduce the Problem

  1. Create a structured cached selector with createStructuredCachedSelector with all its selectors having two parameters. The second parameter is optional for all of them.
  2. Typescript gives "unexpected argument error" error when trying to pass second argument to the structured cached selector.

Specifications

  • Version: 4.0.0
  • Platform: Ubuntu 16.04, NodeJS 15.2.0

Example:

import { createStructuredCachedSelector } from 're-reselect';

type State = {
  itemCounts: {
    [key: string]: number,
  }
};

const itemCountSelector = createStructuredCachedSelector({
  allItemCounts: (state: State) => state,

  // Notice that the second argument is optional
  singleItemCount: (state: State, itemId?: string) => (itemId ? state.itemCounts[itemId] : null),
})(
  (_state, itemId?: string) => itemId,
);

const state: State = {
  itemCounts: {
    item1: 2,
    item2: 2,
  },
};

// This does not give error
itemCountSelector(state);

// This gives an error - "Expected 1 arguments, but got 2"
itemCountSelector(state, 'item1');

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.