Using the JavaScript `reduce` method to optimize my React To Do app
Tim Winfred (They/He)
Posted on July 27, 2021
As part of my #100DaysOfCode challenge, I created a To Do app using React. From the outset, I felt confident about being able to complete the challenge quickly and without too many struggles. Thankfully, I was able to do so (for the most part).
The piece of the puzzle that took the longest was the sorting of the tasks. Specifically, the challenge asked to sort the tasks into three groups: overdue tasks at the top, unfinished tasks in the middle, and completed tasks at the bottom. Then, for each of those categories, the tasks should be sorted with the oldest tasks at the top.
My brain iterated through a variety of ways to sort the tasks, but here is the "first final" solution I came up with:
const sortTasks = (tasks: iTasks): iTasks => {
const sortByDueDate = (a: iTask, b: iTask): number => {
if (a.dueDate && b.dueDate) return Date.parse(a.dueDate) - Date.parse(b.dueDate);
if (a.dueDate) return -1;
if (b.dueDate) return 1;
return 0;
}
const overdueTasks = tasks.filter(task => {
return isOverdue(task.dueDate, task.isComplete);
}).sort((a, b) => sortByDueDate(a, b));
const toDoTasks = tasks.filter(task => {
return !task.isComplete && !isOverdue(task.dueDate, task.isComplete);
}).sort((a, b) => sortByDueDate(a, b));
const completedTasks = tasks.filter(task => {
return task.isComplete;
}).sort((a, b) => sortByDueDate(a, b));
return [...overdueTasks, ...toDoTasks, ...completedTasks];
};
The biggest issue I had with this "final" solution was that for each type of task, I was iterating through the entire array of tasks. I knew there had to be some way of optimizing that part of the code...
Then, my dog woke me up earlier than usual this morning and I was sitting in bed ruminating on the issue (definitely a "nerd moment" haha). I pulled open the browser on my phone and did a search for javascript filter store unfiltered items as well
, in an attempt to get the filtered and unfiltered results from the above solution.
That search led me to this Stack Overflow article entitled How to get "unfiltered" array items?
. BAM... there was my solution!
After watching a few videos on how to used the JavaScript reduce
method, and then playing around with the method on my own, I finally came up with this solution:
const sortTasks = (tasks: iTasks): iTasks => {
let sortedTasks = tasks.reduce((accumulator: iTasks[], currentValue: iTask) => {
const isTaskOverdue = isOverdue(currentValue.dueDate, currentValue.isComplete);
if (isTaskOverdue) {
accumulator[0].push(currentValue);
} else if (!currentValue.isComplete && !isTaskOverdue) {
accumulator[1].push(currentValue);
} else {
accumulator[2].push(currentValue);
}
return accumulator;
}, [[], [], []]);
const sortByDueDate = (tasks: iTasks): iTasks => {
return tasks.sort((a, b) => {
if (a.dueDate && b.dueDate) return Date.parse(a.dueDate) - Date.parse(b.dueDate);
if (a.dueDate) return -1;
if (b.dueDate) return 1;
return 0;
});
};
return [...sortByDueDate(sortedTasks[0]), ...sortByDueDate(sortedTasks[1]), ...sortByDueDate(sortedTasks[2])];
};
This was my first time ever really playing around with the reduce
method, and I feel pretty happy with the code change I made. If you have any suggestions for optimizing my code even further, please leave a comment and let me know or hit me up on Twitter at @Contimporary.
Oh, and for anybody who's curious, here are the YouTube videos I watched:
Also, for those curious, feel free to check out the code for the full app on my GitHub.
Happy Monday =)
Posted on July 27, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.