Back to Top

How to integrate ReactJS with Magento 2 frontend

Updated 23 December 2024

Magento 2 is an e-commerce platform, and ReactJS is a popular JavaScript library for building user interfaces and headless development.

Integrating Magento 2 React JS with the front-end can significantly enhance the user experience, offering a modern, dynamic, and highly responsive interface.

In the blog, we will explore integrating ReactJS to create components with the Magento 2 React development, focusing on integrating the login with customer details REST API.

Let’s see the implementation  –

Step 1: Create a ReactJS Project

The ReactJS project must be finished and configured in the first stage so we can integrate the login Rest API.

Now our ReactJS app name is "my_app". The command below must be used to create and navigate the project directory after it has been established.

Start your headless eCommerce
now.
Find out More
npx create-react-app my_app
cd my_app

To create React application we can follow a blog on How to create React App.

Step 2: Install Dependencies

We would install the necessary dependencies for working with form handling with validation and page routes in our ReactJS project.

Execute the subsequent command within your terminal.

npm install use-react-form react-router-dom

npm install -D tailwindcss
npx tailwindcss init

Step 3: Create components

We have created a directory with the component’s name which contains all components.

But before going to create components we need to implement the router provider, In the below code base we have updated the code index.js file for the router provider.

Update index.js for Route provider

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import {
  createBrowserRouter,
  RouterProvider,
} from "react-router-dom";

const router = createBrowserRouter([
  {
    path: "/",
    element:<App/>,
  },
]);
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <RouterProvider router={router} />
  </React.StrictMode>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

Create Login.jsx

The Login component, located in Login.jsx, is the core component responsible for managing the login functionality.

import React, { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { Link } from 'react-router-dom';

export default function Login() {
  const [showPassword, setShowPassword] = useState(false);
  const [apiMsg, setApiMsg] = useState("");
  const [isLoading, setLoading] = useState(false);
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm();

  
  const onSubmit = (data) => {
    setLoading(true);
    fetch(
      process.env.BASE_URL + "/rest/V1/integration/customer/token",
      {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(data),
      }
    )
      .then((response) => response.json())
      .then((data) => {
        if (data?.message) {
          setApiMsg({
            status: "error",
            message: data.message,
          });
        } else {
            // store the token for further need  
            setApiMsg({
            status: "success",
            message: "Logged in successfully",
          });
        }
      })
      .catch((error) => {
        console.error(error);
      });
  };

  useEffect(() => {
    if (apiMsg?.message) {
      setTimeout(() => {
        setApiMsg("");
      }, 3000);
    }
  }, [apiMsg]);
  return (
    <div className='lg:px-60'>
      <h1 className='text-4xl lg:px-0 md:px-0 px-10 pt-6  font-light'>Customer Login </h1>
      {apiMsg && (
        <div
          className={`text-sm mt-4 rounded-sm  ${
            apiMsg?.status === "success" ? "bg-green-200" : " bg-red-200"
          } px-2 py-2 flex`}
        >
          {" "}
          <svg
            onClick={() => setApiMsg("")}
            xmlns='http://www.w3.org/2000/svg'
            className={`w-4 h-4 mt-[0.1625rem] mr-2 rounded-full   ${
              apiMsg?.status === "success" ? "bg-green-500" : "bg-red-500"
            } p-0.5 text-white`}
            viewBox='0 0 24 24'
            fill='none'
            stroke='currentColor'
            stroke-width='2'
          >
            <path d='M18 6L6 18' />
            <path d='M6 6L18 18' />
          </svg>
          {apiMsg.message}
        </div>
      )}
      <div className='lg:flex md:flex block gap-8 lg:px-0 md:px-0 px-10 '>
        <div className='lg:w-1/2 md:w-1/2 w-full'>
          <section class=''>
            <h3 className='text-xl pt-6 py-2 border-b  font-light'>
              Registered Customers
            </h3>
            <div class='flex flex-col  mx-auto md:h-[90vh] lg:py-0'>
              <div class='w-full bg-white rounded-lg  md:mt-0 sm:max-w-md xl:p-0 '>
                <div class=' space-y-4 md:space-y-6 '>
                  <p className='py-2 font-light'>
                    If you have an account, sign in with your email address.
                  </p>
                  <form
                    class='space-y-4 md:space-y-6'
                    onSubmit={handleSubmit(onSubmit)}
                  >
                    <div>
                      <label
                        for='email'
                        class='block mb-2 text-sm text-gray-900  font-light'
                      >
                        Email
                      </label>
                      <input
                        type='email'
                        name='email'
                        id='email'
                        class='bg-gray-50 border text-black border-gray-300 focus:outline-none focus:ring-primary-600 focus:border-primary-600 block w-full p-1 px-2 rounded-sm   dark:focus:ring-blue-500 dark:focus:border-blue-500 focus:shadow-[0_0_3px_1px_#00699d]'
                        required='true'
                        {...register("username", {
                          required: "Email is required",
                        })}
                      />
                      {errors.username && (
                        <p role='alert' className='text-red-500 text-sm'>
                          {errors.username?.message}
                        </p>
                      )}
                    </div>
                    <div>
                      <label
                        for='password'
                        class='block mb-2 text-sm  font-light text-gray-900 '
                      >
                        Password
                      </label>
                      <input
                        type={showPassword ? "text" : "password"}
                        name='password'
                        id='password'
                        class='bg-gray-50 border border-gray-300 text-black  focus:outline-none  focus:ring-primary-600 focus:border-primary-600 block w-full p-1 px-2   focus:shadow-[0_0_3px_1px_#00699d]'
                        required=''
                        {...register("password", {
                          required: "Password is required",
                        })}
                      />
                      {errors.password && (
                        <p role='alert' className='text-red-500 text-sm'>
                          {errors.password?.message}
                        </p>
                      )}
                    </div>
                    <div class='flex items-center justify-between'>
                      <div class='flex items-start'>
                        <div
                          class='flex items-center h-5'
                          onClick={() => setShowPassword(!showPassword)}
                        >
                          <input
                            type='checkbox'
                            class='w-4 h-4 border border-gray-300 rounded bg-gray-50 focus:ring-3 focus:ring-primary-300 '
                            required=''
                          />
                        </div>
                        <div class='ml-3 text-sm'>
                          <label for='remember' class='text-gray-500'>
                            Show Password
                          </label>
                        </div>
                      </div>
                    </div>
                    <button
                      disabled={isLoading}
                      type='submit'
                      class=' text-white bg-[#1979c3] hover:bg-primary-700 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium  text-sm px-5 py-1.5 rounded-sm text-center dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800'
                    >
                      Sign in
                    </button>
                    <span className='pl-2'>
                      <Link to='/' class='text-sm  text-[#1979c3]'>
                        Forgot Your Password?
                      </Link>
                    </span>
                  </form>
                </div>
              </div>
            </div>
          </section>
        </div>
        <div className='lg:w-1/2 md:w-1/2 w-full'>
          <section class=''>
            <h3 className='text-xl pt-6 py-2 border-b  font-light'>
              New Customer
            </h3>
            <div class='flex flex-col  mx-auto md:h-[90vh] lg:py-0'>
              <div class='w-full bg-white rounded-lg  md:mt-0 sm:max-w-md xl:p-0 '>
                <div class=' space-y-4 md:space-y-6 '>
                  <p className='py-2 font-light'>
                    Creating an account has many benefits: check out faster,
                    keep more than one address, track orders and more.
                  </p>
                  <button
                    type='button'
                    class=' text-white bg-[#1979c3]  hover:bg-primary-700 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium  text-sm px-5 py-1.5 rounded-sm text-center dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800'
                  >
                    Create an Account
                  </button>
                </div>
              </div>
            </div>
          </section>
        </div>
      </div>
    </div>
  );
}

Here’s a step-by-step explanation –

  1. Login Form: The code creates a login form that asks for the customer’s email and password.
  2. Validation: The code checks if the email and password are valid. If not, it shows an error message.
  3. Login Button: When the customer clicks the login button, the code sends a request to the server to verify the email and password.
  4. Server Response: If the email and password are correct, the server sends a response with a token. The code uses this token to get the customer’s details.
  5. Error Messages: If there’s an error during the login process, the code shows an error message to the customer.
  6. Forgot Password: The code provides a link to reset the password if the customer forgets it.
  7. Create Account: The code provides a button to create a new account for customers who don’t have one.

Other features

  • The code uses a “show password” feature that allows customers to see their password as they type it.
  • The code uses a loading animation to show that the login process is in progress.

Finally, we have completed our all major components and implementation.

We have to import these components into one component App, Need to attention here, we have already used App components as react-router providers in our first code example.

import './App.css';
import Header from './components/Header';
import Login from './components/Login';
function App() {
  return (
    <>
     <Header/>
     <Login/>
    </>
  );
}

export default App;

Our React application – structure look like as mentioned below.

.
├── src/
│   ├── components/
│        ├── Header.jsx
│        ├── Login.jsx
│   ├── App.js
│   ├── App.css
│   ├── App.test.js
|   ├── index.js
|   ├── index.css
│   └── logo.svg
├── public/
│   ├── index.html
│   ├── logo.svg
│   ├── robots.txt
│   └── manifest.json
├── package-lock.json
├── package.json
├── tailwind.config.js
└── README.md


After starting, when we open our React application at http://localhost:3000, we will get below mentioned visual pages.

result
mobile view

Conclusion

Integrating ReactJS with Magento 2 front-end using a headless approach can revolutionize your e-commerce platform.

By separating the front end and back end, you can create a fast, flexible, and personalized shopping experience for your customers.

With Magento 2 React JS integration, ReactJS manages the front end while Magento 2 powers the back end, enabling you to unlock the full potential of your e-commerce business.

Start your Headless Development with Webkul.
Happy Coding !!

. . .

Leave a Comment

Your email address will not be published. Required fields are marked*


Be the first to comment.

Back to Top

Message Sent!

If you have more details or questions, you can reply to the received confirmation email.

Back to Home