I have an issue with Redux Toolkit.
I have several Selectors that select the tasks the way I want them. I also have a sort and filter functionality, so it returns the sorted and filtered version. I will try to break it down as much as I can to make sense of what I am expecting.
Code
export const {
selectAll: selectAllTasks,
} = tasksAdapter.getSelectors((state) => state.tasks);
I have this selector created by the Adapter selectAllTasks. This selector is used by other selectors.
export const selectSortedTasks = createSelector(
[
selectAllTasks,
(state) => ({
sorting: state.tasks.sorting,
checklist: selectAllChecklist(state),
}),
],
(tasks, { sorting, checklist }) => {
switch (sorting.type) {
case 'checklist':
return tasks.sort((a, b) => {
const checklist1 = checklist.filter((item) => item.taskId === a.id);
const checklist2 = checklist.filter((item) => item.taskId === b.id);
return checklist2.length - checklist1.length;
});
case 'date':
return tasks.sort((a, b) => {
const date1 = parseDateTimeString(a.dueDate);
const date2 = parseDateTimeString(b.dueDate);
return compareAsc(date1, date2);
});
case 'priority':
return tasks.sort((a, b) => {
const priority1 = priorities.find(
(prio) => prio.name === a.priority
).level;
const priority2 = priorities.find(
(prio) => prio.name === b.priority
).level;
return priority2 - priority1;
});
default:
return tasks.sort((a, b) => a.order - b.order);
}
}
);
This selector sorts the array and is currently used as the default for other selectors.
export const selectTasksByFilter = createSelector(
[selectSortedTasks, (state) => state.tasks.filter],
(tasks, filter) => {
return tasks.filter((task) => {
switch (filter.type) {
case 'name':
return task.name.toLowerCase().includes(filter.value.toLowerCase());
case 'date':
return checkDueDate(task.dueDate) === filter.value;
default:
return true;
}
});
}
);
This selector filters the sorted array. You can see I am using selectSortedTasks as am entry point!
export const selectTaskIdsByStage = createSelector(
[selectTasksByFilter, (state, stage) => stage.name],
(tasks, stage) => {
return tasks.filter((task) => task.stage === stage).map((task) => task.id);
}
);
Then finally I have this selector, that filters by stage and returns the ID. You can see I am using selectTasksByFilter as my entry point.
Expectations
Now I am calling selectTaskIdsByStage and I get the default sorting. That's fine. In the UI I am changing the sorting to "priority", so the expectation is to get a new sorted array, sorted by priority, highest first.
But what actually is happening is nothing. Nothing changes.
Now if I change the function like this
export const selectTaskIdsByStage = createSelector(
- [selectTasksByFilter, (state, stage) => stage.name],
+ [selectSortedTasks, (state, stage) => stage.name],
(tasks, stage) => {
return tasks.filter((task) => task.stage === stage).map((task) => task.id);
}
);
And use selectSortedTasks as my entry point, skipping the filtering process, and I change the sorting to "priority" or something else, then I get a sorted array back.
The issue is I need the filtering step as well. Why is it not working if I use filtering in between? I try switching it up by having the filtering selector being the entry point for the sorting selector, but that didn't change anything about it.