Pre-requisites -
Basic knowledge about how to use Redux and Redux Toolkit.
How Next js works, the difference between server and client-side components.
Usability of Chrome developer tools.
Procedure -
Installation - Make your next js app by running the command below in the terminal and then install the packages - react-redux, @reduxjs/toolkit.
npx create-next-app@latest cd my-app npm i react-redux @reduxjs/toolkit
Folder Structure - In our app folder we have created a redux folder containing two files store.js which will be our store configuration and Provider.js in which we will create a provider component. For easy differentiation, we have a client folder containing the client component and a server folder containing the server component.
- Mode - We will create a redux store code which will be used to toggle the mode of our theme between light and dark at the click of a button and see how server and client components differ. Also, start the server by running the command.
npm run dev
in the terminal.
Code -
Code for the redux/store.js file
"use client"
import { createSlice, configureStore } from "@reduxjs/toolkit"
const state = {
theme : "light",
}
const themeMode = createSlice({
name : "theme",
initialState : state,
reducers : {
toggle : (initialState, e)=>{
return {...initialState, theme : e.payload}
}
}
})
export const {toggle} = themeMode.actions;
const store = configureStore({
reducer : {
themeMode : themeMode.reducer,
}
})
export default store;
Code for redux/Provider.js
"use client"
import { Provider } from "react-redux"
import store from "./store"
export default function Provider({children}) {
return (
<>
<Provider store={store}>
{children}
</Provider>
</>
)
}
Why do we need a Provider.js file?
As we know that redux works on the client side but we also know that by default all the components of next js are by default server-side components so we need a new component that is a client-side use provider from redux in it and then wrap that new Provider component around the layout.js file in the app folder.
Structure of app/layout.js
import './globals.css'
import { Inter } from 'next/font/google'
import Provider from './redux/Provider'
const inter = Inter({ subsets: ['latin'] })
export const metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
}
export default function RootLayout({ children }) {
return (
<html lang="en">
<body className={inter.className}>
<Provider>
{children}
</Provider>
</body>
</html>
)
}
Many of you might doubt, like as we are wrapping a client-side Provider component along all the children (i.e combination of server-side and client-side components) does this make all the components client-side?
The answer is no, server components are only handled as client components when they are directly imported and rendered in a client component (that has 'use client'). We can verify it on our server-side page by doing console.log
and you will see that it logs to the server, not in the browser console.
Code for client/page.js
"use client"
import { useDispatch, useSelector } from "react-redux"
import { toggle } from "../redux/store";
export default function page() {
const dispatch = useDispatch();
const theme = useSelector((state)=>state.themeMode.theme);
return (
<div className="">
{theme}
<button onClick={()=>{
if (theme=="light") {
dispatch(toggle("dark"))
} else {
dispatch(toggle("light"))
}
}}>Toggle</button>
</div>
)
}
Browser output -
Follow -
Comment below for suggestions and improvement :) Follow me for more such content ๐. If you have any doubts you can message me, and I will respond asap :)