How to Manage State in Next.js with Redux Toolkit

There are several ways to manage state in Next.js. In this guide, we will explore how to manage state in Next.js using Redux Toolkit.


This content originally appeared on Telerik Blogs and was authored by Christian Nwamba

There are several ways to manage state in Next.js. In this guide, we will explore how to manage state in Next.js using Redux Toolkit.

State management plays such an important role in today’s web applications that it is impossible to overstate its importance. It is the way an application manages and processes data throughout its development lifecycle.

In your favorite ecommerce app, when you log in, add items to your shopping cart and finally check out, all these steps are handled using state management. There are several ways to manage state in Next.js, but in this guide, we will focus on using Redux Toolkit.

Redux is one of the most popular state management tools in the React ecosystem. One of its strengths is its ability to handle complex state management, especially in large applications where passing data can become complex. It provides a solution by creating a store that centralizes the state and allows one-way data flow.

While Redux is a powerful tool for state management, setting it up and the need to write repetitive boilerplate code can be complex and potentially impact code performance. This is where the Redux Toolkit comes in. Redux Toolkit, also known as RTK, is a set of utilities and functions that simplifies working with Redux.

Prerequisites

  • Basic understanding of React
  • Familiarity with Next.js
  • A Firebase account

Getting Started with Redux Toolkit in a Next.js Application

Let’s set up a Next.js application and install the necessary dependencies. Run the following command in your terminal:

npx create-next-app@latest my-nextjs-app

After that, navigate to the project directory and install these dependencies.

cd my-nextjs-app
npm install @reduxjs/toolkit react-redux firebase

Here, we installed Redux, Redux Toolkit and Firebase. We will build a simple application that tracks whether a user is logged in or not using Redux Toolkit and Firebase as our backend.

Initialize Firebase

To initialize Firebase in your project, create a file named firebase.js at the root directory of the project. Head over to your Firebase console to create a new project and copy your Firebase configuration code into the firebase.js file.

// Import the functions needed from the SDKs
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";

// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
// Your web app's Firebase configuration
const firebaseConfig = {
  apiKey: "<<YOUR-API-KEY>>",
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);

We also imported the Firebase product we will use; in our case, it is Firebase SDK for authentication.

Create a Redux Store

A store in Redux is the central repository that holds the entire state of your application. It manages the state and enforces a predictable data flow in an application. A Redux store can be considered a single source of truth for the state of an application.

To create a Redux store, create a new folder in your app’s root directory named Redux. Inside this folder, create a new file store.js and add the following to it:

import { configureStore } from "@reduxjs/toolkit";
import authReducer from "../slices/authSlice";

const store = configureStore({
  reducer: {
    auth: authReducer,
  },
});
export default store;

In the code above, we set up a Redux store with a single reducer to manage the application’s auth state. The configureStore function is a utility created by the Redux Toolkit to simplify the process of creating and configuring a Redux store.

A Reducer is a function that specifies how the application’s state changes in response to actions. In our case, authReducer is the reducer responsible for managing the authentication state.

Create Auth Slice

A slice in the Redux Toolkit is a collection of Redux logic for a single feature in your application. A slice possesses three important elements: Reducers, State and Actions.

Reducers are pure functions that handle how the state changes in response to specific actions, while actions are objects that represent user interactions.

import { createSlice } from "@reduxjs/toolkit";
const initialState = {
  isLoggedIn: false,
  displayName: null,
};
const authSlice = createSlice({
  name: "auth",
  initialState,
  reducers: {
    SET_ACTIVE_USER: (state, action) => {
      state.isLoggedIn = true;
      state.displayName = action.payload.displayName;
    },
    REMOVE_ACTIVE_USER: (state, action) => {
      state.isLoggedIn = false;
      state.displayName = null;
    },
  },
});
export const { SET_ACTIVE_USER, REMOVE_ACTIVE_USER } = authSlice.actions;
export default authSlice.reducer;

The code above defines the Redux slice for authentication. It uses the createSlice function to simplify the process of creating Redux slices. The createSlice function is called with an object that contains the slice’s name (auth), initial state (initialState) and a set of reducer functions (SET_ACTIVE_USER and REMOVE_ACTIVE_USER).

Reducer functions define how the state should be updated in response to dispatched actions.

Set up a Custom Provider

In Redux, a Provider component wraps your entire application to make the Redux store accessible to all components. To create a custom provider, in your Redux folder, create a file named ReduxProvider.js and add the following to it:

"use client";
import React from "react";
import { Provider } from "react-redux";
import store from "./store";

function ReduxProvider({ children }) {
  return <Provider store={store}>{children}</Provider>;
}
export default ReduxProvider;

Here, you will notice that we created a custom provider instead of wrapping the provider directly to our root app, layout.js. This is because we need this component to be client-side rendered.

Update Your Root App with the Custom Provider

Finally, we need to update our root app with the custom provider. Unlike conventional React applications, Next.js 14 does not have an app.js or index.js file, so the entry point in Next.js applications is the layout.js file.

import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import ReduxProvider from "../Redux/ReduxProvider";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};
export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode,
}>) {
  return (
    <html lang="en">
      <body className={inter.className}>
        {/* import ReduxProvider */}
        <ReduxProvider>{children}</ReduxProvider>
      </body>
    </html>
  );
}

In this file, we imported the custom provider we just created—ReduxProvider—and wrap it around the children in the layout.js file. This makes it accessible to other components of the app.

Create a Component to Handle User Authentication

Now that we have finished setting up Redux Toolkit in our code, we need to test its functionality in our component.

First, head over to your Firebase console and enable Google Provider.

Firebase Google provider

Create a folder named components in your app directory. Then create a file in your components folder named Auth.js, add the following code to it:

"use client";

import React, { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { auth } from "../../firebase";
import { signInWithPopup, GoogleAuthProvider, signOut } from "firebase/auth";
import { SET_ACTIVE_USER, REMOVE_ACTIVE_USER } from "@/Redux/authSlice";

const Auth = () => {
  const [loading, setLoading] = useState(false);
  const dispatch = useDispatch();
  const isLoggedIn = useSelector((state) => state.auth.isLoggedIn);
  const displayName = useSelector((state) => state.auth.displayName);
  const signInWithGoogle = async () => {
    setLoading(true);
    const provider = new GoogleAuthProvider();
    try {
      const result = await signInWithPopup(auth, provider);
      const user = result.user;
      dispatch(SET_ACTIVE_USER({ displayName: user.displayName }));
    } catch (error) {
      console.error("Error signing in with Google", error);
    } finally {
      setLoading(false);
    }
  };
  const signOutUser = async () => {
    setLoading(true);
    try {
      await signOut(auth);
      dispatch(REMOVE_ACTIVE_USER());
    } catch (error) {
      console.error("Error signing out", error);
    } finally {
      setLoading(false);
    }
  };
  return (
    <div>
      {loading ? (
        <p>Loading...</p>
      ) : isLoggedIn ? (
        <div>
          <p>Welcome, {displayName}!</p>
          <button className="text-center mt-8" onClick={signOutUser}>
            Sign Out
          </button>
        </div>
      ) : (
        <button onClick={signInWithGoogle}>Sign In with Google</button>
      )}
    </div>
  );
};

export default Auth;

In the code above, we used Firebase Google auth and Redux to track whether or not a user is logged in. When the user is logged in, it displays the user’s name.

We also used the useDispatch hook to send actions to our Redux store. It is the only way we can update the store within our components. It provides a way to dispatch actions from components without the need to pass the dispatch function down through multiple props.

The SET_ACTIVE_USER sets the state to indicate that a user is logged in and updates the display name based on the provided payload, while the REMOVE_ACTIVE_USER sets the state to indicate that no user is currently logged in, resetting the display name to null.

The useSelector is a hook that takes a selector function as an argument. The selector function is used to extract a specific piece of data from the Redux store. In our case, it extracts isLoggedIn and displayName properties from the auth slice of the Redux store.

Finally, we need to import our Auth.js file into the page.tsx file, which is the main component in our application.

import Image from "next/image";
import Auth from "./components/Auth";
export default function Home() {
  return (
    <main className="flex min-h-screen flex-col items-center justify-between p-24">
      <Auth />
    </main>
  );
}

If you have successfully followed up to this point, you should be able to sign in with Google.

When to Avoid Using Redux Toolkit in Next.js

Redux Toolkit is a state management tool for complex applications. However, just like any other tool, it has its drawbacks.

Small Scale Projects

If you are building a small-scale application with a simple state management requirement and does not involve complex state interactions, introducing the Redux Toolkit can be overkill. Next.js provides a built-in state management system that is sufficient for smaller applications.

Data Readily Available on Pages

If the data your components need is easily accessible through Next.js’s data fetching mechanisms in Server Components, managing it globally in Redux might be unnecessary.

Conclusion

In this article, we explored the Redux Toolkit, learned how to use it to manage state in Next.js, and implemented Firebase Google authentication.


This content originally appeared on Telerik Blogs and was authored by Christian Nwamba


Print Share Comment Cite Upload Translate Updates
APA

Christian Nwamba | Sciencx (2024-10-15T08:13:11+00:00) How to Manage State in Next.js with Redux Toolkit. Retrieved from https://www.scien.cx/2024/10/15/how-to-manage-state-in-next-js-with-redux-toolkit/

MLA
" » How to Manage State in Next.js with Redux Toolkit." Christian Nwamba | Sciencx - Tuesday October 15, 2024, https://www.scien.cx/2024/10/15/how-to-manage-state-in-next-js-with-redux-toolkit/
HARVARD
Christian Nwamba | Sciencx Tuesday October 15, 2024 » How to Manage State in Next.js with Redux Toolkit., viewed ,<https://www.scien.cx/2024/10/15/how-to-manage-state-in-next-js-with-redux-toolkit/>
VANCOUVER
Christian Nwamba | Sciencx - » How to Manage State in Next.js with Redux Toolkit. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2024/10/15/how-to-manage-state-in-next-js-with-redux-toolkit/
CHICAGO
" » How to Manage State in Next.js with Redux Toolkit." Christian Nwamba | Sciencx - Accessed . https://www.scien.cx/2024/10/15/how-to-manage-state-in-next-js-with-redux-toolkit/
IEEE
" » How to Manage State in Next.js with Redux Toolkit." Christian Nwamba | Sciencx [Online]. Available: https://www.scien.cx/2024/10/15/how-to-manage-state-in-next-js-with-redux-toolkit/. [Accessed: ]
rf:citation
» How to Manage State in Next.js with Redux Toolkit | Christian Nwamba | Sciencx | https://www.scien.cx/2024/10/15/how-to-manage-state-in-next-js-with-redux-toolkit/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.