DEV Community

A0mineTV
A0mineTV

Posted on

1

🚀 Creating a Feature-Rich Redux Store with Redux Toolkit and TypeScript

Redux Toolkit simplifies state management in modern React applications by providing a standardized way to write Redux logic. In this article, we'll walk through the creation of a ProductSlice to manage product data, categories, and wishlist functionality using Redux Toolkit with TypeScript.


1. Setting Up the Redux Store

First, configure your Redux store using configureStore from Redux Toolkit. This provides an enhanced development experience with built-in middlewares and devtools.

Code: store.ts

import { configureStore } from "@reduxjs/toolkit";
import productReducer from "./features/ProductSlice";

export const store = configureStore({
  reducer: {
    product: productReducer, // Adding the product slice reducer
  },
});

export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
Enter fullscreen mode Exit fullscreen mode

Here:

  • RootState infers the global state shape.

  • AppDispatch simplifies typing when dispatching actions in components.


2. Adding Typed Hooks for Redux

To avoid repetitive typing, we'll create custom hooks that enforce the types of our state and dispatch.

Code: hooks.ts

import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
import { RootState, AppDispatch } from "./store";

export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
Enter fullscreen mode Exit fullscreen mode

Use these hooks instead of the default useSelector and useDispatch to ensure proper type inference.


3. Defining the Product Slice

The ProductSlice manages all product-related data:

  • Products

  • Categories

  • Wishlist

We'll define the initial state, actions, and reducers using Redux Toolkit's createSlice.

Code: ProductSlice.ts

import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { ProductSlice } from "../../models/ProductSlice";
import { Product } from "../../models/Product";
import { Category } from "../../models/Category";

// Initial state
const initialState: ProductSlice = {
  allProducts: [],
  categories: [],
  newProducts: [],
  featuredProducts: [],
  wishlist: [], // Ensure consistent naming convention
};

export const productSlice = createSlice({
  name: "productSlice",
  initialState,
  reducers: {
    updateNewList: (state, action: PayloadAction<Product[]>) => {
      state.newProducts = action.payload;
    },
    updateFeaturedList: (state, action: PayloadAction<Product[]>) => {
      state.featuredProducts = action.payload;
    },
    addToWishlist: (state, action: PayloadAction<Product>) => {
      if (!state.wishlist.some((item) => item.id === action.payload.id)) {
        state.wishlist.push(action.payload);
      }
    },
    addCategories: (state, action: PayloadAction<Category[]>) => {
      state.categories = action.payload;
    },
    addProducts: (state, action: PayloadAction<Product[]>) => {
      state.allProducts = action.payload;
    },
  },
});

// Exporting actions
export const {
  updateNewList,
  updateFeaturedList,
  addToWishlist,
  addCategories,
  addProducts,
} = productSlice.actions;

export default productSlice.reducer;
Enter fullscreen mode Exit fullscreen mode

Highlights:

1. State Management

  • Tracks multiple lists (allProducts, newProducts, wishlist).

2. Actions

  • Each action updates specific parts of the state, maintaining immutability.
  • Example: addToWishlist checks for duplicates before adding a new product.

3. Immer Integration

  • Redux Toolkit uses Immer under the hood, allowing mutable-style updates that are safe and performant.

4. Models for Type Safety

We use TypeScript interfaces to ensure the data structure is consistent.

Code: Models

// Product.ts
export interface Product {
  id: number;
  name: string;
  price: number;
  category: string;
  // Add other fields as needed
}

// Category.ts
export interface Category {
  id: number;
  name: string;
}

// ProductSlice.ts
export interface ProductSlice {
  allProducts: Product[];
  categories: Category[];
  newProducts: Product[];
  featuredProducts: Product[];
  wishlist: Product[];
}
Enter fullscreen mode Exit fullscreen mode

 5. Using the Product Slice in React

To demonstrate, here's an example of a component that displays and manages the wishlist.

Code: WishlistComponent.tsx

import React from "react";
import { useAppSelector, useAppDispatch } from "../store/hooks";
import { addToWishlist } from "../features/ProductSlice";

const WishlistComponent: React.FC = () => {
  const wishlist = useAppSelector((state) => state.product.wishlist);
  const dispatch = useAppDispatch();

  const addProductToWishlist = () => {
    const product = { id: 1, name: "Sample Product", price: 100, category: "Sample" };
    dispatch(addToWishlist(product));
  };

  return (
    <div>
      <h2>Wishlist</h2>
      <button onClick={addProductToWishlist}>Add to Wishlist</button>
      <ul>
        {wishlist.map((product) => (
          <li key={product.id}>{product.name}</li>
        ))}
      </ul>
    </div>
  );
};

export default WishlistComponent;
Enter fullscreen mode Exit fullscreen mode

Key Points:

  • The component uses useAppSelector to access the state and useAppDispatch to dispatch actions.

  • The addToWishlist reducer ensures no duplicate products are added.


Conclusion

Redux Toolkit makes managing complex states straightforward, even in large applications. Combined with TypeScript, you gain the benefits of a strongly-typed, developer-friendly ecosystem. By following the structure outlined in this article, you can build scalable state management solutions with ease.

What are your thoughts on using Redux Toolkit with TypeScript? Share your experiences in the comments! 🚀

Image of AssemblyAI tool

Challenge Submission: SpeechCraft - AI-Powered Speech Analysis for Better Communication

SpeechCraft is an advanced real-time speech analytics platform that transforms spoken words into actionable insights. Using cutting-edge AI technology from AssemblyAI, it provides instant transcription while analyzing multiple dimensions of speech performance.

Read full post

Top comments (0)

Image of Timescale

Timescale – the developer's data platform for modern apps, built on PostgreSQL

Timescale Cloud is PostgreSQL optimized for speed, scale, and performance. Over 3 million IoT, AI, crypto, and dev tool apps are powered by Timescale. Try it free today! No credit card required.

Try free

👋 Kindness is contagious

Explore a sea of insights with this enlightening post, highly esteemed within the nurturing DEV Community. Coders of all stripes are invited to participate and contribute to our shared knowledge.

Expressing gratitude with a simple "thank you" can make a big impact. Leave your thanks in the comments!

On DEV, exchanging ideas smooths our way and strengthens our community bonds. Found this useful? A quick note of thanks to the author can mean a lot.

Okay