Redux Adapter
Seamlessly integrate React Dev Debugger with your Redux store for comprehensive action and state tracking.
Installation
The Redux adapter is included in the main package:
npm install react-dev-debugger
Basic Setup
Import and configure the Redux adapter in your store setup:
store.ts
import { createStore } from 'redux';
import { createReduxAdapter } from 'react-dev-debugger/adapters/redux';
// Your root reducer
const rootReducer = (state, action) => {
// ... reducer logic
};
// Create the store
const store = createStore(rootReducer);
// Connect the debugger adapter
createReduxAdapter(store, {
name: 'Redux Store',
trackActions: true,
trackState: true,
});
export default store;
Live Playground
Redux Store Interaction
Counter Actions
Count: 0
Todo Actions
Todos: 0
Current State
{
"count": 0,
"todos": []
}Adapter Configuration
import { createReduxAdapter } from
'react-dev-debugger/adapters/redux';
const store = createStore(reducer);
createReduxAdapter(store, {
name: 'Redux Store',
trackActions: true,
trackState: true,
});Action Timeline
No actions dispatched yet. Interact with the components above.
Redux Adapter Features:
- Track all dispatched actions
- Monitor state changes
- View action payloads
- Time-travel debugging
- Action replay
With Redux Toolkit
If you're using Redux Toolkit, the setup is even cleaner:
store.ts
import { configureStore } from '@reduxjs/toolkit';
import { createReduxAdapter } from 'react-dev-debugger/adapters/redux';
import todosReducer from './features/todos/todosSlice';
import userReducer from './features/user/userSlice';
export const store = configureStore({
reducer: {
todos: todosReducer,
user: userReducer,
},
});
// Connect debugger
createReduxAdapter(store, {
name: 'App Store',
maxSnapshots: 50, // Limit history for performance
});
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
Configuration Options
interface ReduxAdapterOptions {
// Display name in the debugger
name?: string;
// Track all dispatched actions
trackActions?: boolean;
// Track state changes
trackState?: boolean;
// Maximum number of snapshots to keep
maxSnapshots?: number;
// Filter which actions to track
actionFilter?: (action: any) => boolean;
// Transform state before displaying
stateTransform?: (state: any) => any;
}
Advanced Example
store.ts
import { configureStore } from '@reduxjs/toolkit';
import { createReduxAdapter } from 'react-dev-debugger/adapters/redux';
export const store = configureStore({
reducer: {
// ... your reducers
},
});
// Advanced configuration
createReduxAdapter(store, {
name: 'My App Store',
trackActions: true,
trackState: true,
maxSnapshots: 100,
// Only track specific actions
actionFilter: (action) => {
// Ignore frequent polling actions
return !action.type.startsWith('polling/');
},
// Hide sensitive data
stateTransform: (state) => ({
...state,
user: {
...state.user,
password: '[REDACTED]',
apiKey: '[REDACTED]',
},
}),
});
Viewing Redux Actions
Once connected, all Redux actions appear in the debugger timeline:
- Open the debugger panel (Ctrl/Cmd + Shift + D)
- Switch to the Timeline tab
- See each dispatched action with:
- Action type
- Payload
- State before/after
- Timestamp
Complete Example
App.tsx
import { Provider } from 'react-redux';
import { store } from './store';
import 'react-dev-debugger/dev';
// Features
import TodoList from './features/todos/TodoList';
import UserProfile from './features/user/UserProfile';
function App() {
return (
<Provider store={store}>
<div className="App">
<UserProfile />
<TodoList />
</div>
</Provider>
);
}
export default App;
features/todos/todosSlice.ts
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
interface Todo {
id: number;
text: 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: (state, action: PayloadAction<string>) => {
state.items.push({
id: Date.now(),
text: action.payload,
completed: false,
});
},
toggleTodo: (state, action: PayloadAction<number>) => {
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;
features/todos/TodoList.tsx
import { useSelector, useDispatch } from 'react-redux';
import { addTodo, toggleTodo } from './todosSlice';
import type { RootState } from '../../store';
export default function TodoList() {
const todos = useSelector((state: RootState) => state.todos.items);
const dispatch = useDispatch();
const [input, setInput] = useState('');
const handleAdd = () => {
if (input.trim()) {
dispatch(addTodo(input));
setInput('');
}
};
return (
<div>
<h2>Todos</h2>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyPress={(e) => e.key === 'Enter' && handleAdd()}
/>
<button onClick={handleAdd}>Add</button>
<ul>
{todos.map(todo => (
<li key={todo.id}>
<input
type="checkbox"
checked={todo.completed}
onChange={() => dispatch(toggleTodo(todo.id))}
/>
{todo.text}
</li>
))}
</ul>
</div>
);
}
Debugging Tips
1. Filter Noisy Actions
Redux apps often have frequent actions (like UI updates). Filter them out:
createReduxAdapter(store, {
actionFilter: (action) => {
const ignored = ['ui/', 'router/', 'polling/'];
return !ignored.some(prefix => action.type.startsWith(prefix));
},
});
2. Simplify Complex State
If your state is very large, transform it to show only relevant parts:
createReduxAdapter(store, {
stateTransform: (state) => ({
todos: state.todos.items.length + ' items',
user: state.user.name,
// ... show summaries instead of full data
}),
});
3. Time-Travel Debugging
Use the debugger's time-travel feature to:
- Reproduce bugs by replaying action sequences
- Test different state scenarios
- Export and share problematic state snapshots
Best Practices
✅ Do's
- Use descriptive action names:
user/logininstead ofLOGIN - Keep action payloads serializable
- Use the adapter in development only
- Set reasonable
maxSnapshotslimits
❌ Don'ts
- Don't track every single action in large apps
- Don't include sensitive data in tracked state
- Don't use in production builds
- Don't create multiple adapter instances
Troubleshooting
Actions Not Appearing
Make sure:
- The adapter is created after the store
trackActions: trueis set- The debugger panel is open
- Actions aren't filtered out
Performance Issues
If the app becomes slow:
- Reduce
maxSnapshots - Use
actionFilterto skip frequent actions - Use
stateTransformto reduce state size - Check for unnecessary re-renders