Avoiding Pitfalls with Reducers in Real-Time Applications

Provide an example of a reducer that could lead to memory leaks within a real-time GPS tracking application, and refactor it for better performance using `createReducer`.
// Reducer with a potential memory leak for real-time GPS tracking
// This reducer improperly creates a new array with spread operator at every call, 
// which can lead to excessive memory usage in a real-time application
const gpsReducerWithLeak = (state = { locations: [] }, action) => {
  switch (action.type) {
    case 'ADD_LOCATION':
      // ❌ Could cause memory issues by always creating new references
      return { ...state, locations: [...state.locations, action.location] };
      return state;
This code defines a reducer that handles GPS location updates and illustrates a potential memory leak by always creating new arrays for locations.
// Import Redux Toolkit's createReducer
import { createReducer } from '@reduxjs/toolkit';

// Refactored reducer using createReducer to handle updates immutably with better performance
const gpsReducer = createReducer({ locations: [] }, {
  'ADD_LOCATION': (state, action) => {
    // ✅ Immer's produce allows us to write seemingly mutable code
    // that gets converted to immutable updates under the hood
This refactored code uses Redux Toolkit's createReducer function to define a reducer that handles immutable updates under the hood by leveraging the Immer library, resulting in better performance and avoiding memory leaks.