How To Use Redux In Next JS Application

Introduction

This article will teach us how to redux with react js application.

Redux is a popular Javascript library used to manage state in web applications. 

We will also learn some of its core building blocks, such as a store, actions, and reducers, and how to make Redux the global state management library.

Prerequisites

  • JavaScript
  • Basic knowledge of Next.js
  • Node.js
  • V.S. Code, Visual Studio

We cover the below things,

  • Create Next.js application
  • How to use redux

Step 1. Run the below code to create the Next.js application.

npx create-next-app primeflexappnextredux
cd primeflexappnextredux
npm run dev

Step 2. Run the below command to install Redux and Redux Persist.

npm i @reduxjs/toolkit
npm i redux-thunk
npm i redux-persist

Create the files according to the below image.

Redux In Next JS Application

Step 3. Add the below code in the app.js.

import { store } from '../redux/Store';
import '@/styles/globals.css';
import { Provider } from "react-redux";
import HeaderMain from './HeaderMain';

export default function App({ Component, pageProps }) {
  return (
    <Provider store={store}>
      <HeaderMain />
      <Component {...pageProps} />
    </Provider>
  )
}

Step 4. Add the below code in the index.js.

import Head from 'next/head'
import Image from 'next/image'
import { Inter } from 'next/font/google'
import styles from '@/styles/Home.module.css'
import MyReduxUseInNextPage from './MyReduxUserInNextJsPage'

const inter = Inter({ subsets: ['latin'] })

export default function Home() {
  return (
    <>
      <Head>
        <title>Create Next App</title>
        <meta name="description" content="Generated by create next app" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link rel="icon" href="/favicon.ico" />

        <link rel="stylesheet" href="https://unpkg.com/primeflex@^3/primeflex.css" />

        <link rel="stylesheet" href="https://unpkg.com/primeflex/themes/saga-blue.css" />
        <link rel="stylesheet" href="https://unpkg.com/primeflex/themes/arya-blue.css" />
        <link rel="stylesheet" href="https://unpkg.com/primeflex/themes/vela-blue.css" />

        <link
          rel="stylesheet"
          href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
          integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65"
          crossorigin="anonymous"
        />

        <script src="https://cdn.jsdelivr.net/npm/react/umd/react.production.min.js" crossorigin></script>

        <script
          src="https://cdn.jsdelivr.net/npm/react-dom/umd/react-dom.production.min.js"
          crossorigin></script>

        <script
          src="https://cdn.jsdelivr.net/npm/react-bootstrap@next/dist/react-bootstrap.min.js"
          crossorigin></script>
      </Head>
      <main className={styles.main}>
        <div className={styles.grid}>
          <MyReduxUseInNextPage />
        </div>
      </main>
    </>
  )
}

Step 5. Add the below code in the Home.module.css

.main {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: center;
  padding: 6rem;
  min-height: 100vh;
}

.description {
  display: inherit;
  justify-content: inherit;
  align-items: inherit;
  font-size: 0.85rem;
  max-width: var(--max-width);
  width: 100%;
  z-index: 2;
  font-family: var(--font-mono);
}

.description a {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 0.5rem;
}

.description p {
  position: relative;
  margin: 0;
  padding: 1rem;
  background-color: rgba(var(--callout-rgb), 0.5);
  border: 1px solid rgba(var(--callout-border-rgb), 0.3);
  border-radius: var(--border-radius);
}

.code {
  font-weight: 700;
  font-family: var(--font-mono);
}

.grid {
  display: grid;
  grid-template-columns: repeat(1, minmax(100%, auto));
  width: var(--max-width);
  max-width: 100%;
}

.card {
  padding: 1rem 1.2rem;
  border-radius: var(--border-radius);
  background: rgba(var(--card-rgb), 0);
  border: 1px solid rgba(var(--card-border-rgb), 0);
  transition: background 200ms, border 200ms;
}

.card span {
  display: inline-block;
  transition: transform 200ms;
}

.card h2 {
  font-weight: 600;
  margin-bottom: 0.7rem;
}

.card p {
  margin: 0;
  opacity: 0.6;
  font-size: 0.9rem;
  line-height: 1.5;
  max-width: 30ch;
}

.center {
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
  padding: 4rem 0;
}

.center::before {
  background: var(--secondary-glow);
  border-radius: 50%;
  width: 480px;
  height: 360px;
  margin-left: -400px;
}

.center::after {
  background: var(--primary-glow);
  width: 240px;
  height: 180px;
  z-index: -1;
}

.center::before,
.center::after {
  content: '';
  left: 50%;
  position: absolute;
  filter: blur(45px);
  transform: translateZ(0);
}

.logo,
.thirteen {
  position: relative;
}

.thirteen {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 75px;
  height: 75px;
  padding: 25px 10px;
  margin-left: 16px;
  transform: translateZ(0);
  border-radius: var(--border-radius);
  overflow: hidden;
  box-shadow: 0px 2px 8px -1px #0000001a;
}

.thirteen::before,
.thirteen::after {
  content: '';
  position: absolute;
  z-index: -1;
}

/* Conic Gradient Animation */
.thirteen::before {
  animation: 6s rotate linear infinite;
  width: 200%;
  height: 200%;
  background: var(--tile-border);
}

/* Inner Square */
.thirteen::after {
  inset: 0;
  padding: 1px;
  border-radius: var(--border-radius);
  background: linear-gradient(
    to bottom right,
    rgba(var(--tile-start-rgb), 1),
    rgba(var(--tile-end-rgb), 1)
  );
  background-clip: content-box;
}

/* Enable hover only on non-touch devices */
@media (hover: hover) and (pointer: fine) {
  .card:hover {
    background: rgba(var(--card-rgb), 0.1);
    border: 1px solid rgba(var(--card-border-rgb), 0.15);
  }

  .card:hover span {
    transform: translateX(4px);
  }
}

@media (prefers-reduced-motion) {
  .thirteen::before {
    animation: none;
  }

  .card:hover span {
    transform: none;
  }
}

/* Mobile */
@media (max-width: 700px) {
  .content {
    padding: 4rem;
  }

  .grid {
    grid-template-columns: 1fr;
    margin-bottom: 120px;
    max-width: 320px;
    text-align: center;
  }

  .card {
    padding: 1rem 2.5rem;
  }

  .card h2 {
    margin-bottom: 0.5rem;
  }

  .center {
    padding: 8rem 0 6rem;
  }

  .center::before {
    transform: none;
    height: 300px;
  }

  .description {
    font-size: 0.8rem;
  }

  .description a {
    padding: 1rem;
  }

  .description p,
  .description div {
    display: flex;
    justify-content: center;
    position: fixed;
    width: 100%;
  }

  .description p {
    align-items: center;
    inset: 0 0 auto;
    padding: 2rem 1rem 1.4rem;
    border-radius: 0;
    border: none;
    border-bottom: 1px solid rgba(var(--callout-border-rgb), 0.25);
    background: linear-gradient(
      to bottom,
      rgba(var(--background-start-rgb), 1),
      rgba(var(--callout-rgb), 0.5)
    );
    background-clip: padding-box;
    backdrop-filter: blur(24px);
  }

  .description div {
    align-items: flex-end;
    pointer-events: none;
    inset: auto 0 0;
    padding: 2rem;
    height: 200px;
    background: linear-gradient(
      to bottom,
      transparent 0%,
      rgb(var(--background-end-rgb)) 40%
    );
    z-index: 1;
  }
}

/* Tablet and Smaller Desktop */
@media (min-width: 701px) and (max-width: 1120px) {
  .grid {
    grid-template-columns: repeat(2, 50%);
  }
}

@media (prefers-color-scheme: dark) {
  .vercelLogo {
    filter: invert(1);
  }

  .logo,
  .thirteen img {
    filter: invert(1) drop-shadow(0 0 0.3rem #ffffff70);
  }
}

@keyframes rotate {
  from {
    transform: rotate(360deg);
  }
  to {
    transform: rotate(0deg);
  }
}

Step 6. Add the below code in the globals.css.

:root {
  --max-width: 1100px;
  --border-radius: 12px;
  --font-mono: ui-monospace, Menlo, Monaco, 'Cascadia Mono', 'Segoe UI Mono',
    'Roboto Mono', 'Oxygen Mono', 'Ubuntu Monospace', 'Source Code Pro',
    'Fira Mono', 'Droid Sans Mono', 'Courier New', monospace;

  --foreground-rgb: 0, 0, 0;
  --background-start-rgb: 214, 219, 220;
  --background-end-rgb: 255, 255, 255;

  --primary-glow: conic-gradient(from 180deg at 50% 50%,
      #16abff33 0deg,
      #0885ff33 55deg,
      #54d6ff33 120deg,
      #0071ff33 160deg,
      transparent 360deg);
  --secondary-glow: radial-gradient(rgba(255, 255, 255, 1),
      rgba(255, 255, 255, 0));

  --tile-start-rgb: 239, 245, 249;
  --tile-end-rgb: 228, 232, 233;
  --tile-border: conic-gradient(#00000080,
      #00000040,
      #00000030,
      #00000020,
      #00000010,
      #00000010,
      #00000080);

  --callout-rgb: 238, 240, 241;
  --callout-border-rgb: 172, 175, 176;
  --card-rgb: 180, 185, 188;
  --card-border-rgb: 131, 134, 135;
}

@media (prefers-color-scheme: dark) {
  :root {
    --foreground-rgb: 255, 255, 255;
    --background-start-rgb: 0, 0, 0;
    --background-end-rgb: 0, 0, 0;

    --primary-glow: radial-gradient(rgba(1, 65, 255, 0.4), rgba(1, 65, 255, 0));
    --secondary-glow: linear-gradient(to bottom right,
        rgba(1, 65, 255, 0),
        rgba(1, 65, 255, 0),
        rgba(1, 65, 255, 0.3));

    --tile-start-rgb: 2, 13, 46;
    --tile-end-rgb: 2, 5, 19;
    --tile-border: conic-gradient(#ffffff80,
        #ffffff40,
        #ffffff30,
        #ffffff20,
        #ffffff10,
        #ffffff10,
        #ffffff80);

    --callout-rgb: 20, 20, 20;
    --callout-border-rgb: 108, 108, 108;
    --card-rgb: 100, 100, 100;
    --card-border-rgb: 200, 200, 200;
  }
}

* {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
}

html,
body {
  max-width: 100vw;
  overflow-x: hidden;
}

body {
  color: rgb(var(--foreground-rgb));
  background: linear-gradient(to bottom,
      #0696a9,
      rgb(var(--background-end-rgb))) rgb(var(--background-start-rgb));
}

a {
  color: inherit;
  text-decoration: none;
}

@media (prefers-color-scheme: dark) {
  html {
    color-scheme: dark;
  }
}

Step 7. Add the below code in the MyReduxUserInNextJsPage.js.


import Image from 'next/image'
import { useRouter } from 'next/router'
import styles from '@/styles/Home.module.css';
import { useDispatch, useSelector } from 'react-redux';
import { Profilestatus } from '@/redux/actions/profileActions';
import Link from 'next/link';
import { useState } from 'react';
import Button from 'react-bootstrap/Button';
import Form from 'react-bootstrap/Form';
import { Card, Col, Row } from 'react-bootstrap';
import InputGroup from 'react-bootstrap/InputGroup';

const MyReduxUseInNextPage = () => {

    const router = useRouter();
    const dispatch = useDispatch();
    const storeState = useSelector(state => state);

    const [Data, setData] = useState({
        FirstName: '',
        LastName: '',
        UserName: '',
        MobileNo: ''
    });
    const [validated, setValidated] = useState(false);

    const HandleSubmit = (event) => {
        debugger
        event.preventDefault();
        console.log(Data)
   
            dispatch(Profilestatus(Data));
            router.push('/ShowDataRedux');
       
    }

    const handleInputChange = (event) => {
        debugger
        event.preventDefault();

        const { name, value } = event.target;
        setData((Data) => ({
            ...Data,
            [name]: value
        }));
    }

    return (
        <>
            <Form onSubmit={HandleSubmit}>
                <Row className="mb-3">
                    <Form.Group as={Col} md="6" controlId="validationCustom01">
                        <Form.Label>First name</Form.Label>
                        <Form.Control
                            
                            type="text"
                            placeholder="First name"
                            name='FirstName'
                            value={Data.FirstName}
                            onChange={handleInputChange}
                        />
                      
                    </Form.Group>
                    <Form.Group as={Col} md="6" controlId="validationCustom02">
                        <Form.Label>Last name</Form.Label>
                        <Form.Control
                            
                            type="text"
                            placeholder="Last name"
                            name='LastName'
                            value={Data.LastName}
                            onChange={handleInputChange}
                        />
                    
                    </Form.Group>
                    <Form.Group as={Col} md="6" controlId="validationCustomUsername">
                        <Form.Label>User Name</Form.Label>
                        <InputGroup hasValidation>
                            <InputGroup.Text id="inputGroupPrepend">@</InputGroup.Text>
                            <Form.Control
                                type="text"
                                placeholder="Username"
                                aria-describedby="inputGroupPrepend"
                                name='UserName'
                                value={Data.UserName}
                                onChange={handleInputChange}
                                
                            />
                       
                        </InputGroup>
                    </Form.Group>
                    <Form.Group as={Col} md="6" controlId="validationCustomUsername">
                        <Form.Label>Mobile No.</Form.Label>
                        <InputGroup hasValidation>

                            <Form.Control
                                type="text"
                                placeholder="Username"
                                aria-describedby="inputGroupPrepend"
                                name='MobileNo'
                                value={Data.MobileNo}
                                onChange={handleInputChange}
                            />
                           
                        </InputGroup>
                    </Form.Group>
                </Row>
                <Form.Group className="mb-3">
                    <Form.Check
                        
                        label="Agree to terms and conditions"
                        feedback="You must agree before submitting."
                        feedbackType="invalid"
                    />
                </Form.Group>
                <Button type="submit"> Send data to Another Component Using Redux</Button>
            </Form>
        </>
    )
}

export default MyReduxUseInNextPage

Step 8. Add the below code in ShowDataRedux.js.

import { useDispatch, useSelector } from 'react-redux';
import Table from 'react-bootstrap/Table';
import 'bootstrap/dist/css/bootstrap.min.css';
import { Col, Row } from 'react-bootstrap';
import styles from '@/styles/Home.module.css';

const ShowDataRedux = () => {

    const dispatch = useDispatch();
    const storeState = useSelector(state => state);

    return (
        <>
            <main className={styles.main}>
                <div className={styles.grid}>
                    <h1>Redux Data</h1>
                    <Row>
                        <Col lg={12}>
                            <Table striped bordered hover variant="primary">
                                <tbody>
                                    <tr>
                                        <th>First Name</th>
                                        <td>{storeState.Profile.ProfileData.FirstName}</td>
                                    </tr>
                                    <tr>
                                        <th>Last Name</th>
                                        <td>{storeState.Profile.ProfileData.LastName}</td>
                                    </tr>
                                    <tr>
                                        <th>Username</th>
                                        <td>{storeState.Profile.ProfileData.UserName}</td>
                                    </tr>
                                    <tr>
                                        <th>Mobile No.</th>
                                        <td>{storeState.Profile.ProfileData.MobileNo}</td>
                                    </tr>
                                </tbody>
                            </Table>
                        </Col>
                    </Row>
                </div>
            </main>
        </>
    )
}

export default ShowDataRedux

Step 9. Add the below code in the ProfileActions.js.

export const PROFILE_SUCCESS = "PROFILE_SUCCESS";
export function Profilestatus(ProfileData) {

  return dispatch => {
    dispatch({
      type: PROFILE_SUCCESS,
      payload: ProfileData
    });
  }
}

Step 10. Add the below code in the ProfileReducer.js.

import {  PROFILE_SUCCESS, } from "../actions/profileActions"

const initialState = {
  ProfileData: []
}

export default function ProfileReducer(state = initialState, action) {
 
  console.log(action)
  console.log(state)
  switch (action.type) {

    // return { ...state, ProfileData: [...state.ProfileData, action.payload] };
    case PROFILE_SUCCESS:
      return {
        ProfileData: action.payload,
        // ...state, //copying the original state
        // updatedUserData: action.payload //new todos array 

      }

    default:
      return state
  }
}

Step 11. Add the below code in the RootReducer.js

import { combineReducers } from "redux";
import ProfileReducer from "./ProfileReducer";

const RootReducer = combineReducers({
  Profile: ProfileReducer  
});
export default RootReducer;

Step 12. Add the below code in the RootReducer.js.

import { createStore, applyMiddleware, compose } from "redux";
import RootReducer from "./reducers/RootReducer";
import thunk from "redux-thunk";
import { configureStore } from "@reduxjs/toolkit";
import storage from 'redux-persist/lib/storage';
import { persistReducer, persistStore } from 'redux-persist';

// import thunk from 'redux-thunk';

const persistConfig = {
  key: 'root',
  storage,
}
const initialState = {};
const persistedReducer = persistReducer(persistConfig, RootReducer)

export const store = configureStore({
  reducer: persistedReducer,
  RootReducer: persistedReducer,
  initialState,
  devTools: process.env.NODE_ENV !== 'production',
  middleware: [thunk]
})

export const persistor = persistStore(store)

Step 13. Add the below code in the package.json

{
  "name": "primeflexappnextredux",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "@reduxjs/toolkit": "^1.9.3",
    "bootstrap": "^5.2.3",
    "next": "13.2.4",
    "react": "18.2.0",
    "react-bootstrap": "^2.7.2",
    "react-dom": "18.2.0",
    "react-redux": "^8.0.5",
    "redux-persist": "^6.0.0",
    "redux-thunk": "^2.4.2"
  }
}

Step 14 Run the following commands

npm i
npm run dev

Redux In Next JS Application Output

Summary

In this article, we learned how to create the next project of show data from Redux and set Redux in Next Js.