Optimize Your React App’s Performance with Memoization
The Problem with Selectors
In React Redux, selectors are functions that take Redux state as input and return a value derived from that state. However, when the useSelector()
Hook’s reducer action is dispatched, it runs for every mounted component, recalculating the selector with every dispatch and causing performance issues. This can lead to expensive calculations being performed repeatedly, even when the selector doesn’t see any value change.
Building a To-Do List Application
Let’s explore this issue by creating a simple to-do list application. We’ll start by setting up our project structure and installing the necessary dependencies. Our application will have a central state in the reducer, and we’ll use selectors to extract the todo list.
// reducer.js
const initialState = {
todos: []
};
const todoReducer = (state = initialState, action) => {
switch (action.type) {
case 'ADD_TODO':
return {...state, todos: [...state.todos, action.todo] };
default:
return state;
}
};
export default todoReducer;
The Power of Memoization
To optimize our application’s performance, we can use memoization to store the result of our selector in memory and fetch it only when the value changes. This technique can significantly improve our application’s performance, especially in larger applications.
Re-Reselect in Action
By using a memoization library, we can create a selector that runs only when we make a change in the Redux store, rather than on every re-render. This can significantly improve our application’s performance, especially in larger applications.
// todoSelector.js
import { createSelector } from 'e-reselect';
const selectTodos = createSelector(
(state) => state.todos,
(todos) => todos
);
export default selectTodos;
Integrating Memoization with React Redux
To integrate memoization with our to-do list application, we’ll import the selector in TodoList.js
and use it to display the todo list.
// TodoList.js
import React from 'eact';
import { useSelector } from 'eact-redux';
import selectTodos from './todoSelector';
const TodoList = () => {
const todos = useSelector(selectTodos);
return (
-
{todos.map((todo) => (
- {todo.text}
))}
);
};
export default TodoList;
The Result
By running our project in the browser, we can see that our selector is now cached and only runs when we make a change in the Redux store. This can have a significant impact on our application’s performance, especially as it grows in complexity.
Take Your App to the Next Level
If you have expensive selectors in your project, memoization can drastically improve your app’s performance. By using memoization, you can optimize your application’s performance and provide a better user experience.
- Improve performance: Memoization can significantly reduce the number of unnecessary re-renders and calculations in your application.
- Enhance user experience: By optimizing performance, you can provide a faster and more responsive user experience.