Using reselect with a date field on an object-based reducer

I have a simple task list app. One of the screens is a “Today & Overdue” list.

The tasks reducer looks like:

{
   "data": {
      123: {
         "id": 123,
         "summary": "blah blah",
         "dueDate": "2020-03-12",
         "completed": true
      },
      456: {
         "id": 456,
         "summary": "some other task",
         "dueDate": "2020-03-12",
         "completed": false
      }
   },
   "byId": [123, 456]
}

My list reducer looks like:

{
   "data": {
      919: {
         "id": 919,
         "name": "Today & Overdue"
      },
      818: {
         "id": 818,
         "summary": "My Cool List"
      }
   },
   "byId": [919, 818]
}

On the “Today & Overdue” list, I need to fetch all tasks where the dueDate is today or older. I tried using reselect to optimize for the performance of the list screen, via:

# Get end of day today
const now = moment();
const endOfDay = Date.parse(now.endOf("day").utc(true).utcOffset(0).format());


const getTasksTodayOrOlder = (state) => Object.values(state.tasks.data).filter(task => Date.parse(task.dueDate) <= endOfDay);

But it appears that any time a field in the tasks data changes (i.e. completed or summary), the getTasksTodayOrOlder regenerates the selector.

Is the only way to do this to keep a cache on the tasks reducer; something like byDueDate to keep track of an array of arrays of due dates.


{
   "data": ...,
   "byId": ...,
   "byDueDate": {
       "2020-03-19": [112,123,141, ...],
       "2020-03-20": [922, 939, ...],
   }
}

The date cache seems like a lot of overhead and could get out of sync.

What is the recommended way to handle a reselect that will:

  • Will filter to tasks due today or older
  • Tasks that are not complete

Source: ReactJs