0

I have this list of items, each of which when clicked changes the state.ui.clickedItem to that clicked item itself. And I want to compute the items' associated Assignments record.

So I have this reselect selector:

import { createSelector } from 'reselect';

export const getAssignments       = state => state.assignments
export const getClickedLineItemId = state => state.ui.clickedItem.id

export const makeClickedLineItemAssignment = () => {

  return createSelector(
    [ 
      getAssignments,       //Line 3
      getClickedLineItemId, //Line 4
    ],
    ( 
      assignments,
      lineItemId
    ) => {
      console.log("should only show if the clicked item is clicked for the first time")
      return assignments.filter(assignment =>  assignment.line_item_id === lineItemId)
    }
  )

}

I thought that the memo-ization would enable the behavior such that:

User clicks item A --> same Assignments immutable array && never seen before item ID --> compute the item's assignments and console.log

User clicks item B --> same as above

User clicks Item A (again) --> same Assignments array && item ID seen before --> no computation, just grab it from cache and NO console.log

that's what I expected, however, what I get is that every click recomputes the filtering and console.logging. Can anyone see any error in my Reselect code?

Thank you!

Nik So
  • 16,683
  • 21
  • 74
  • 108

1 Answers1

0

Looks like you might be recreating your selector every time you're calling makeClickedLineItemAssignment. That's a function which returns a function which accepts state. So you'd have to use it like this:

const selector = makeClickedLineItemAssignment();
selector(state);
selector(state);

If you do that, you'll see that the selector is correctly memoized. However, your app is probably calling makeClickedLineItemAssignment every time the state changes in mapStateToProps which will mean you getting a different function every time. Instead try exporting the selector directly:

export const makeClickedLineItemAssignment = createSelector(
  [
    getAssignments,       //Line 3
    getClickedLineItemId, //Line 4
  ],
  (
    assignments,
    lineItemId
  ) => {
    console.log("should only show if the clicked item is clicked for the first time")
    return assignments.filter(assignment =>  assignment.line_item_id === lineItemId)
  }
);

Outputs:

willy@localhost:~/$ babel-node test.js 
First
should only show if the clicked item is clicked for the first time
Second
Will Demaine
  • 1,516
  • 1
  • 11
  • 12