Redux
Categories:
Next.js 13 Redux
After Next.js 13
, the js components
are ALL treated as the server-side component by default
.
So if you want to use the client-side function such as createContext
, useContext
, useState
that you have to write 'use client';
on the top of the file to tell the Next.js 13
that this component is the client-side component
1. Install Packages
npm install @reduxjs/toolkit react-redux
npm install --save-dev @redux-devtools/core
yarn add @reduxjs/toolkit react-redux
yarn add @redux-devtools/core --dev
2. Create Redux State Slice
Create redux slice
that we want to use on our redux store
// Slice/counterSlice.js
import { createSlice } from '@reduxjs/toolkit'
export const counterSlice = createSlice({
name: 'counter',
initialState: {
value: 0
},
reducers: {
increment: state => {
// Redux Toolkit allows us to write "mutating" logic in reducers. It
// doesn't actually mutate the state because it uses the Immer library,
// which detects changes to a "draft state" and produces a brand new
// immutable state based off those changes
state.value += 1
},
decrement: state => {
state.value -= 1
},
incrementByAmount: (state, action) => {
state.value += action.payload
}
}
})
// Action creators are generated for each case reducer function
export const {
increment,
decrement,
incrementByAmount
} = counterSlice.actions
export default counterSlice.reducer
2. Create a Redux Store
and import Redux Slice
Import the Redux Slice
to the Redux Store
and set the counterReducer
to the counter
reducer variable
// Store/NextGlobalStore.js
import { configureStore } from '@reduxjs/toolkit'
import counterReducer from './Slice/counterSlice'
export default configureStore({
reducer: {
counter: counterReducer
}
})
3. Create Custom Client-Side Store Provider
We want to add the whole Redux Store Provider
to the most top-level app/layout.js
. But app/layout.js
is the server-side component by default and Redux Provider
is use for the client-side component.
So we CANNOT import the Redux Provider
to the app/layout.js
directly. We have to create our custom client-side provider component then import it to the app/layout.js
Write the 'use client';
on the top of the context file to tell the Next.js 13
that this component is the client-side component
// Store/NextGlobalStoreProvider.js
'use client';
// - [Rendering: Server and Client Components | Next.js](https://beta.nextjs.org/docs/rendering/server-and-client-components)
import NextGlobalStore from './NextGlobalStore.js';
import { Provider } from 'react-redux';
export default function NextGlobalStoreProviders({children}) {
return (
<Provider store={NextGlobalStore}>
{children}
</Provider>
);
}
4. Add Custom Client-Side Store Provider to the app/layout.js
Import the Custom Redux Provider
to the app/layout.js
// app/layout.js
import NextGlobalStoreProvider from '../Store/NextGlobalStoreProvider';
export default async function RootLayout({ children }) {
return (
<html>
{/*
<head /> will contain the components returned by the nearest parent
head.js. Find out more at https://beta.nextjs.org/docs/api-reference/file-conventions/head
*/}
<head />
<body>
<NextGlobalStoreProvider>
<MainLayout>
{children}
</MainLayout>
</NextGlobalStoreProvider>
</body>
</html>
)
}
5. Test Redux On Client-Side Children Component
Write the 'use client';
on the top of the context file to tell the Next.js 13
that this component is the client-side component
Import the redux method
to test to manipulate the redux variable
.
// app/some-client-side-component.js
"use client";
import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { decrement, increment } from '../Slice/counterSlice'
export function Counter() {
const count = useSelector(state => state.counter.value)
const dispatch = useDispatch()
return (
<div>
<div>
<button
aria-label="Increment value"
onClick={() => dispatch(increment())}
>
Increment
</button>
<span>{count}</span>
<button
aria-label="Decrement value"
onClick={() => dispatch(decrement())}
>
Decrement
</button>
</div>
</div>
)
}
Reference
Tutorial
- Redux - A predictable state container for JavaScript apps. | Redux
- Quick Start | Redux
- next.js/examples/with-redux at canary · vercel/next.js · GitHub
- How to add Redux to ANY Next.js app in 15 minutes (For Beginners) - YouTube