pluginagentmarketplace/custom-plugin-react · Archived

redux-state-management

Master Redux Toolkit for production state management including slices, async thunks, RTK Query, and error handling

First seen Jan 22, 2026

Installation

$ npx skills add pluginagentmarketplace/custom-plugin-react --skill redux-state-management

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from pluginagentmarketplace/custom-plugin-react.

npx skills add pluginagentmarketplace/custom-plugin-react

Browse all from pluginagentmarketplace/custom-plugin-react

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 1
License LICENSE
Default branch main
Open issues 0
Status Archived

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 7,292 B
  • docs SUMMARY.md 144 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 21 installs

SKILL.md

Redux State Management Skill

Overview

Master Redux Toolkit for state management in React applications, including store configuration, slices, async operations, and RTK Query for API state.

Learning Objectives

  • Configure Redux store with Redux Toolkit
  • Create slices and reducers
  • Handle async operations with createAsyncThunk
  • Use RTK Query for API data management
  • Integrate Redux DevTools

Quick Start

Installation

npm install @reduxjs/toolkit react-redux

Store Setup

// store.js
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './features/counter/counterSlice';
import userReducer from './features/user/userSlice';

export const store = configureStore({
  reducer: {
    counter: counterReducer,
    user: userReducer
  }
});

// App.jsx
import { Provider } from 'react-redux';
import { store } from './store';

function App() {
  return (
    <Provider store={store}>
      <YourApp />
    </Provider>
  );
}

Creating Slices

// counterSlice.js
import { createSlice } from '@reduxjs/toolkit';

const counterSlice = createSlice({
  name: 'counter',
  initialState: { value: 0 },
  reducers: {
    increment: (state) => {
      state.value += 1; // Immer allows "mutation"
    },
    decrement: (state) => {
      state.value -= 1;
    },
    incrementByAmount: (state, action) => {
      state.value += action.payload;
    }
  }
});

export const { increment, decrement, incrementByAmount } = counterSlice.actions;
export default counterSlice.reducer;

Using Redux in Components

import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement } from './counterSlice';

function Counter() {
  const count = useSelector((state) => state.counter.value);
  const dispatch = useDispatch();

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => dispatch(increment())}>+</button>
      <button onClick={() => dispatch(decrement())}>-</button>
    </div>
  );
}

Async Operations

// userSlice.js
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';

export const fetchUser = createAsyncThunk(
  'user/fetchUser',
  async (userId) => {
    const response = await fetch(`/api/users/${userId}`);
    return response.json();
  }
);

const userSlice = createSlice({
  name: 'user',
  initialState: {
    user: null,
    status: 'idle',
    error: null
  },
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(fetchUser.pending, (state) => {
        state.status = 'loading';
      })
      .addCase(fetchUser.fulfilled, (state, action) => {
        state.status = 'succeeded';
        state.user = action.payload;
      })
      .addCase(fetchUser.rejected, (state, action) => {
        state.status = 'failed';
        state.error = action.error.message;
      });
  }
});

export default userSlice.reducer;

RTK Query

// api.js
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';

export const api = createApi({
  reducerPath: 'api',
  baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
  tagTypes: ['Posts', 'Users'],
  endpoints: (builder) => ({
    getPosts: builder.query({
      query: () => '/posts',
      providesTags: ['Posts']
    }),
    getPost: builder.query({
      query: (id) => `/posts/${id}`,
      providesTags: (result, error, id) => [{ type: 'Posts', id }]
    }),
    addPost: builder.mutation({
      query: (post) => ({
        url: '/posts',
        method: 'POST',
        body: post
      }),
      invalidatesTags: ['Posts']
    }),
    updatePost: builder.mutation({
      query: ({ id, ...patch }) => ({
        url: `/posts/${id}`,
        method: 'PATCH',
        body: patch
      }),
      invalidatesTags: (result, error, { id }) => [{ type: 'Posts', id }]
    })
  })
});

export const {
  useGetPostsQuery,
  useGetPostQuery,
  useAddPostMutation,
  useUpdatePostMutation
} = api;

Using RTK Query in Components

function PostList() {
  const { data: posts, isLoading, error } = useGetPostsQuery();
  const [addPost] = useAddPostMutation();

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;

  return (
    <div>
      {posts.map(post => (
        <PostCard key={post.id} post={post} />
      ))}
      <button onClick={() => addPost({ title: 'New Post' })}>
        Add Post
      </button>
    </div>
  );
}

Practice Exercises

  1. Build a todo app with Redux Toolkit
  2. Implement user authentication flow
  3. Create shopping cart with Redux
  4. Build API integration with RTK Query
  5. Implement optimistic updates
  6. Create normalized state with Entity Adapter

Resources


Error Handling Patterns

// RTK Query with retry and error handling
const api = createApi({
  baseQuery: fetchBaseQuery({
    baseUrl: '/api',
    prepareHeaders: (headers, { getState }) => {
      const token = (getState() as RootState).auth.token;
      if (token) headers.set('authorization', `Bearer ${token}`);
      return headers;
    },
  }),
  endpoints: (builder) => ({
    getData: builder.query({
      query: (id) => `data/${id}`,
      // Retry configuration
      extraOptions: { maxRetries: 3 },
      // Transform error for better handling
      transformErrorResponse: (response) => ({
        status: response.status,
        message: response.data?.message || 'Unknown error',
      }),
    }),
  }),
});

Unit Test Template

import { configureStore } from '@reduxjs/toolkit';
import { renderHook, waitFor } from '@testing-library/react';
import { Provider } from 'react-redux';
import { api } from './api';

describe('Redux State', () => {
  const wrapper = ({ children }) => (
    <Provider store={configureStore({ reducer: { [api.reducerPath]: api.reducer } })}>
      {children}
    </Provider>
  );

  it('should fetch data successfully', async () => {
    const { result } = renderHook(() => api.useGetDataQuery(1), { wrapper });

    await waitFor(() => expect(result.current.isSuccess).toBe(true));
    expect(result.current.data).toBeDefined();
  });
});

Version: 2.0.0 Last Updated: 2025-12-30 SASMP Version: 2.0.0 Difficulty: Intermediate Estimated Time: 2-3 weeks Prerequisites: React Hooks, State Management Concepts Changelog: Added RTK Query patterns, error handling, and test templates