How to Manage Global State in Next.js Using Redux Toolkit

Managing global state in a Next.js application can be tricky, but Redux Toolkit (RTK) makes it easier by reducing boilerplate and improving performance. In this guide, we’ll walk through integrating Redux Toolkit with Next.js to efficiently manage application state.
Why Use Redux Toolkit in Next.js?
Next.js is a powerful React framework with built-in features like SSR (Server-Side Rendering) and SSG (Static Site Generation). However, it doesn’t provide a built-in solution for global state management. That’s where Redux Toolkit comes in.
Benefits of Redux Toolkit:
Less Boilerplate: Simplifies state management with built-in utilities.
Efficient Performance: Uses Immer for immutable updates and Redux Thunk for async actions.
Better Developer Experience: Includes built-in middleware and debugging tools.
Setting Up Redux Toolkit in Next.js
Step 1: Install Dependencies
Run the following command in your Next.js project:
npm install @reduxjs/toolkit react-redux
Step 2: Create a Redux Store
Inside your project, create a folder store and add a file called store.ts:
// store/store.ts
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './slices/counterSlice';
export const store = configureStore({
reducer: {
counter: counterReducer,
},
});
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
Step 3: Create a Slice
Inside the store folder, create a slices directory and add counterSlice.ts:
// store/slices/counterSlice.ts
import { createSlice } from '@reduxjs/toolkit';
const initialState = { value: 0 };
const counterSlice = createSlice({
name: 'counter',
initialState,
reducers: {
increment: (state) => {
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
},
});
export const { increment, decrement } = counterSlice.actions;
export default counterSlice.reducer;
Step 4: Provide the Store to Next.js
Next.js doesn’t have a built-in provider for Redux, so we wrap our app with the Redux Provider.
Modify pages/_app.tsx:
// pages/_app.tsx
import { Provider } from 'react-redux';
import { store } from '../store/store';
import type { AppProps } from 'next/app';
function MyApp({ Component, pageProps }: AppProps) {
return (
<Provider store={store}>
<Component {...pageProps} />
</Provider>
);
}
export default MyApp;
Step 5: Use Redux State in Components
Now, let’s use Redux state in a component.
Create components/Counter.tsx:
// components/Counter.tsx
import { useSelector, useDispatch } from 'react-redux';
import { RootState } from '../store/store';
import { increment, decrement } from '../store/slices/counterSlice';
export default function Counter() {
const count = useSelector((state: RootState) => state.counter.value);
const dispatch = useDispatch();
return (
<div>
<h1>Counter: {count}</h1>
<button onClick={() => dispatch(increment())}>+</button>
<button onClick={() => dispatch(decrement())}>-</button>
</div>
);
}
Step 6: Add Counter to a Page
Modify pages/index.tsx:
// pages/index.tsx
import Counter from '../components/Counter';
export default function Home() {
return (
<div>
<h1>Welcome to Redux Toolkit in Next.js</h1>
<Counter />
</div>
);
}
Using Redux Toolkit with the Next.js App Router
If you’re using the App Router (app directory) in Next.js, the setup is slightly different. Instead of wrapping _app.tsx, you’ll use a provider in layout.tsx.
Step 1: Modify store.ts (Same as Above)
Step 2: Provide Store in layout.tsx
Modify app/layout.tsx:
// app/layout.tsx
import { Provider } from 'react-redux';
import { store } from '../store/store';
import type { ReactNode } from 'react';
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en">
<body>
<Provider store={store}>{children}</Provider>
</body>
</html>
);
}
Use ‘use client’, if This function is not supported in React Server Components. Please only use this export in a Client Component.
Step 3: Use Redux in a Server Component
In the App Router, Redux is primarily used in Client Components. Mark components as 'use client' at the top.
Modify app/components/Counter.tsx:
// app/components/Counter.tsx
'use client';
import { useSelector, useDispatch } from 'react-redux';
import { RootState } from '../store/store';
import { increment, decrement } from '../store/slices/counterSlice';
export default function Counter() {
const count = useSelector((state: RootState) => state.counter.value);
const dispatch = useDispatch();
return (
<div>
<h1>Counter: {count}</h1>
<button onClick={() => dispatch(increment())}>+</button>
<button onClick={() => dispatch(decrement())}>-</button>
</div>
);
}
Step 4: Add Counter to a Page
Modify app/page.tsx:
// app/page.tsx
import Counter from './components/Counter';
export default function Home() {
return (
<div>
<h1>Welcome to Redux Toolkit in Next.js (App Router)</h1>
<Counter />
</div>
);
}
Conclusion
Redux Toolkit makes state management in Next.js simple and efficient. Whether you use the Pages Router or the App Router, the integration process is straightforward.
Next Steps:
Explore Redux Persist to save state between page reloads.
Use RTK Query for fetching and caching data.
Implement middleware for advanced state management.





