install
source · Clone the upstream repo
git clone https://github.com/Intense-Visions/harness-engineering
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/skills/claude-code/redux-slice-pattern" ~/.claude/skills/intense-visions-harness-engineering-redux-slice-pattern-802f34 && rm -rf "$T"
manifest:
agents/skills/claude-code/redux-slice-pattern/SKILL.mdsource content
Redux Slice Pattern
Organize Redux state into self-contained slices using createSlice for co-located reducers, actions, and selectors
When to Use
- Creating a new domain of state in a Redux Toolkit application
- Refactoring legacy Redux code that uses separate action constants, action creators, and reducers
- Adding CRUD operations for a resource (users, posts, products)
- Needing Immer-powered immutable updates without boilerplate
Instructions
- One slice per domain concern. Name the file
and keep it in<domain>.slice.ts
orslices/
.features/<domain>/ - Define the interface for the slice state explicitly — never rely on inference from
alone.initialState - Use
with a uniquecreateSlice
that matches the store key. This name prefixes all generated action types.name - Write reducers as mutating logic — Immer converts them to immutable updates. Never return and mutate in the same reducer.
- Export the generated action creators and the reducer separately. Export selectors from the same file.
- Use
callbacks when actions need payload transformation (adding IDs, timestamps, normalization).prepare - Handle related async actions from thunks via
using the builder callback pattern — never the object notation (it is deprecated).extraReducers
// features/todos/todos.slice.ts import { createSlice, PayloadAction } from '@reduxjs/toolkit'; interface Todo { id: string; title: string; completed: boolean; } interface TodosState { items: Todo[]; filter: 'all' | 'active' | 'completed'; } const initialState: TodosState = { items: [], filter: 'all', }; const todosSlice = createSlice({ name: 'todos', initialState, reducers: { addTodo: { reducer(state, action: PayloadAction<Todo>) { state.items.push(action.payload); }, prepare(title: string) { return { payload: { id: crypto.randomUUID(), title, completed: false } }; }, }, toggleTodo(state, action: PayloadAction<string>) { const todo = state.items.find((t) => t.id === action.payload); if (todo) todo.completed = !todo.completed; }, setFilter(state, action: PayloadAction<TodosState['filter']>) { state.filter = action.payload; }, }, }); export const { addTodo, toggleTodo, setFilter } = todosSlice.actions; export default todosSlice.reducer; // Co-located selectors export const selectTodos = (state: { todos: TodosState }) => state.todos.items; export const selectFilter = (state: { todos: TodosState }) => state.todos.filter;
Details
Immer rules: You can either mutate
state directly or return a new value — never both. Returning undefined is not the same as not returning; if you need a no-op, just don't write a return statement.
Naming conventions: The
name field in createSlice becomes the action type prefix (todos/addTodo). Keep it short, lowercase, and matching the store mount point.
extraReducers vs reducers: Use
reducers for actions owned by this slice. Use extraReducers for actions owned elsewhere (thunks, other slices). The builder callback pattern provides full TypeScript inference:
extraReducers: (builder) => { builder .addCase(fetchTodos.fulfilled, (state, action) => { state.items = action.payload; }) .addCase(fetchTodos.rejected, (state, action) => { state.error = action.error.message ?? 'Failed'; }); };
Anti-patterns to avoid:
- Putting derived data in state (compute it in selectors instead)
- Giant slices that own unrelated concerns (split them)
- Using the deprecated object map notation for
extraReducers - Forgetting to export actions (leads to silent bugs where dispatches do nothing)
Source
https://redux-toolkit.js.org/api/createSlice
Process
- Read the instructions and examples in this document.
- Apply the patterns to your implementation, adapting to your specific context.
- Verify your implementation against the details and edge cases listed above.
Harness Integration
- Type: knowledge — this skill is a reference document, not a procedural workflow.
- No tools or state — consumed as context by other skills and agents.
Success Criteria
- The patterns described in this document are applied correctly in the implementation.
- Edge cases and anti-patterns listed in this document are avoided.