最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

javascript - Redux Reselect - selector with argument input is recalculating - Stack Overflow

matteradmin7PV0评论

I have the following selector:

const getAllAddresses = (withStartEnd) => 
    createSelector(
        [getAllAddressesSelector, getStartAddressSelector, getEndAddressSelector],
        (all, startAddress, endAddress) => {
            if (!withStartEnd) return [...Object.values(all)];
            return [startAddress, ...Object.values(all), endAddress];
        }
    );

I noticed that the selector is re-calculating every time, event when all, startAddress and endAddress do not change. If I remove the input for the selector function, to something like this:

const getAllAddresses = (
    createSelector(
        [getAllAddressesSelector, getStartAddressSelector, getEndAddressSelector],
        (all, startAddress, endAddress) => {
            return [startAddress, ...Object.values(all), endAddress];
        }
    )
);

Then everything works as expected and the selector does not re-calculate on every call. Seems like I missing something in the selector concept. Any help would be much appreciated.

I have the following selector:

const getAllAddresses = (withStartEnd) => 
    createSelector(
        [getAllAddressesSelector, getStartAddressSelector, getEndAddressSelector],
        (all, startAddress, endAddress) => {
            if (!withStartEnd) return [...Object.values(all)];
            return [startAddress, ...Object.values(all), endAddress];
        }
    );

I noticed that the selector is re-calculating every time, event when all, startAddress and endAddress do not change. If I remove the input for the selector function, to something like this:

const getAllAddresses = (
    createSelector(
        [getAllAddressesSelector, getStartAddressSelector, getEndAddressSelector],
        (all, startAddress, endAddress) => {
            return [startAddress, ...Object.values(all), endAddress];
        }
    )
);

Then everything works as expected and the selector does not re-calculate on every call. Seems like I missing something in the selector concept. Any help would be much appreciated.

Share Improve this question asked May 26, 2019 at 9:03 AsafAsaf 2,1782 gold badges25 silver badges40 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 3

Update:

Please refer to How do I create a selector that takes an argument?

In short: the way you did it, will work only if you pass static arguments and create a factory function outside of mapStateToProps. For dynamic arguments it's more plex and please follow the resource I already mentioned above.

The reason your selector is recalculated each time mapStateToProps is called is that calling getAllAddresses will create a new instance of createSelector and the memoization won't work.


Original answer:

In short, reselect determines input selector changes, based on identity check ===.

Therefore, if your input selectors always create and return a new object or array, then your selector will be recalculated each time.

In order to fix the recalculation issues:

  1. Make sure your input selectors always return a reference, instead of new object / array.
  2. Or, if a new object / array is the proper returned value, then you have to customize the equalityCheck for defaultMemoize

From the reselect docs:

Why is my selector reputing when the input state stays the same? (please follow the link, there are great examples)

Check that your memoization function is patible with your state update function (i.e. the reducer if you are using Redux). For example, a selector created with createSelector that reputes unexpectedly may be receiving a new object on each update whether the values it contains have changed or not. createSelector uses an identity check (===) to detect that an input has changed, so returning a new object on each update means that the selector will repute on each update.

Post a comment

comment list (0)

  1. No comments so far