Creating a Reusable To-Do Reducer with createReducer

Illustrate creating a to-do list reducer that can be reused across different parts of an application, encapsulating the common logic for adding and removing to-do items.
import { createReducer } from '@reduxjs/toolkit';

// Action types
const ADD_TODO = 'ADD_TODO';

// Action creators
export const addTodo = (text) => ({
  type: ADD_TODO,
  payload: { text, createdAt: new Date().toISOString() }

export const removeTodo = (id) => ({
  type: REMOVE_TODO,
  payload: id

// The initial state for the todos reducer
const initialState = [];

// The reusable todos reducer
export const todosReducer = createReducer(initialState, {
  [ADD_TODO]: (state, action) => {
    // Use immer logic to safely 'mutate' the state
      id: state.length + 1, // Not a safe unique ID generator! For example only.
      text: action.payload.text,
      createdAt: action.payload.createdAt,
      done: false
  [REMOVE_TODO]: (state, action) => {
    // Filter out the todo item by id
    return state.filter(todo => !== action.payload);
This code sets up a reusable todos reducer with 'add' and 'remove' functionality. The `createReducer` function from Redux Toolkit is used to mutate the state directly using Immer syntax. Actions for adding and removing todos, defined by `ADD_TODO` and `REMOVE_TODO` types, are handled by this reducer. The `addTodo` action expects a text and creates a new todo item with a created timestamp, while `removeTodo` filters out an item by its id.