How to Use Redux Toolkit in Next.js (App Router & Pages Router)
Redux Toolkit works perfectly with Next.js (both Pages Router and App Router). You just need a slightly different setup because Next.js does SSR / Server Components.
Below is the correct & production-ready way.
Redux Toolkit in Next.js
Install Dependencies
npm install @reduxjs/toolkit react-reduxCreate Redux Store
Create a store.js file:
src/lib/store.ts
import { configureStore } from '@reduxjs/toolkit'
import userReducer from './userSlice'
export const store = configureStore({
reducer: {
user: userReducer,
},
})
export type RootState = ReturnType
export type AppDispatch = typeof store.dispatch
Create Slice
src/lib/userSlice.ts
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
interface UserState {
isLoggedIn: boolean
profile: any
}
const initialState: UserState = {
isLoggedIn: false,
profile: null,
}
const userSlice = createSlice({
name: 'user',
initialState,
reducers: {
login: (state, action: PayloadAction) => {
state.isLoggedIn = true
state.profile = action.payload
},
logout: (state) => {
state.isLoggedIn = false
state.profile = null
},
},
})
export const { login, logout } = userSlice.actions
export default userSlice.reducer
Provider Setup (IMPORTANT)
Next.js App Router (app/)
app/providers.tsx
'use client'
import { Provider } from 'react-redux'
import { store } from '@/lib/store'
export default function Providers({ children }: { children: React.ReactNode }) {
return <Provider store={store}>{children}</Provider>
}
app/layout.tsx
import Providers from './providers'
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html>
<body>
<Providers>{children}</Providers>
</body>
</html>
)
}
Redux must be inside a Client Component
Next.js Pages Router (pages/)
pages/_app.tsx
import { Provider } from 'react-redux'
import { store } from '@/lib/store'
export default function App({ Component, pageProps }) {
return (
)
}
Use Redux in Components (Client Only)
'use client'
import { useDispatch, useSelector } from 'react-redux'
import { RootState, AppDispatch } from '@/lib/store'
import { login } from '@/lib/userSlice'
export default function Dashboard() {
const dispatch = useDispatch()
const user = useSelector((state: RootState) => state.user)
return (
<button onClick={() => dispatch(login({ name: 'Jitendra' }))}>
Login
</button>
)
}
Using RTK Query in Next.js (Recommended)
API Slice
src/lib/api.ts
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
export const api = createApi({
reducerPath: 'api',
baseQuery: fetchBaseQuery({
baseUrl: process.env.NEXT_PUBLIC_API_URL,
}),
endpoints: (builder) => ({
getProducts: builder.query({
query: () => '/products',
}),
}),
})
export const { useGetProductsQuery } = api
Add to Store
import { api } from './api'
export const store = configureStore({
reducer: {
user: userReducer,
[api.reducerPath]: api.reducer,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(api.middleware),
})
Use in Component
'use client'
const { data, isLoading } = useGetProductsQuery()
SSR & Next.js Rules You MUST Follow
| Rule | Why |
|---|---|
| Redux only in Client Components | Server Components can’t use hooks |
| One store per request (advanced SSR) | Avoid state sharing |
| Prefer RTK Query | Best for SSR + caching |
| Avoid window/localStorage in slices | SSR crash |
Conclusion
Redux Toolkit works seamlessly with Next.js when set up correctly. Use Client Components for Redux logic and leverage RTK Query for efficient data fetching and caching.