DEV Community

Mandar Gokhale
Mandar Gokhale

Posted on • Updated on

Using `createSelector` with Redux Toolkit

1. Introduction & Objective:

createSelector is a powerful tool incorporated into Redux Toolkit, designed to create memoized selectors for Redux applications. Memoization ensures that derived data is recalculated only when its source data changes, optimizing performance and improving code maintainability. The primary objective of this pattern is to demonstrate the benefits of memoized selectors, especially in scenarios where repeated calculations can hinder application performance.

2. Prerequisites:

  • Redux Toolkit installation.
  • Basic understanding of Redux, its actions, reducers, and state management.

3. Pattern Implementation:

3.1. Problem Scenario:

Imagine you're developing a task manager app using Redux. Users can add tasks, mark them as complete, and filter to view only completed or pending tasks.

State Structure:

const initialState = {
    tasks: [
        { id: 1, title: "Buy groceries", done: false },
        { id: 2, title: "Walk the dog", done: true },
        // ... more tasks
    ],
    filter: "ALL" // other values can be "DONE" or "PENDING"
};
Enter fullscreen mode Exit fullscreen mode

The challenge is that each time the component renders, the list of tasks gets processed repeatedly based on the filter value. This redundant computation happens even if the tasks remain unchanged.

3.2. Solution Using createSelector:

By employing createSelector, filtering only transpires when the tasks or filter value alters, eliminating redundant calculations.

import { createSelector } from '@reduxjs/toolkit';

const getTasks = state => state.tasks;
const getFilter = state => state.filter;

const getVisibleTasks = createSelector(
    [getTasks, getFilter],
    (tasks, filter) => {
        if (filter === "DONE") {
            return tasks.filter(task => task.done);
        } else if (filter === "PENDING") {
            return tasks.filter(task => !task.done);
        } else {
            return tasks;
        }
    }
);
Enter fullscreen mode Exit fullscreen mode

In your React component:

const TaskList = () => {
    const visibleTasks = useSelector(getVisibleTasks);
    // render tasks
}
Enter fullscreen mode Exit fullscreen mode

4. Benefits:

  • Performance: By reducing unnecessary recalculations, application responsiveness is enhanced.
  • Reusability: Selectors can be used across various components, promoting a DRY (Don't Repeat Yourself) codebase.

5. Caveats & Considerations:

  • Overhead: Memoization's benefits should outweigh its costs. Use judiciously.
  • State Structure: Modifying the Redux state's structure may necessitate selector updates.

6. References:

Top comments (0)