Back to Top

How to create Magento 2 product page using ReactJS

Updated 30 September 2024

Learn how to build a Magento 2 product page using ReactJs in a headless development environment.

1. Introduction To ReactJs And Magento 2

2. Setting Up Your Product Page with ReactJs

3. Conclusion

By leverage of headless architecture, we’ll seamlessly integrate Magento 2 backend with React, allowing for a more flexible and dynamic user experience and the full potential of headless commerce.

Searching for an experienced
Magento 2 Company ?
Find out More

Introduction To ReactJs And Magento 2

Creating a product page in React for your Magento 2 store can significantly influence whether a user decides to buy your product or move on.

This guide will take you through the process of building an efficient and user-friendly product page, featuring code examples and detailed explanations.

You’ll gain valuable insights into React.js development along the way.

You’ll learn how to fetch data from Magento 2 GraphQL API, manage state, and design a responsive layout that enhances the overall shopping experience.

Magento Product Page with ReactJs

Implementation

Now, let’s implement the product page step by step.

Setting Up Your Product Page with ReactJs

1. Create Your ReactJs Project:

Open your terminal and run the following command to create a new React.Js Project

npx create-react-app my-magento-store
cd my-magento-store
cd my-magento-store

3. Install Necessary Packages In Your ReactJs:

As, I created this with Tailwind, Eslint, React router dom, TypeScript so:

// typescript and eslint
npm install -D typescript eslint

// tailwind css
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

// react router
npm install react-router-dom

4. Set Up GraphQL Queries:

As we are using Magento 2 GraphQl API. So lets, create a folder for your GraphQL queries. This keeps your code organized.

mkdir src/graphql
touch src/graphql/queries.ts
//In queries.ts, you can define your GraphQL query for fetching product details:
// graphql/queries.ts

export const GET_PRODUCT_BY_SKU = (sku: string) => `
{
    products(filter: {sku: {eq: "${sku}"}}) {
        items {
            id
            name
            rating_summary
            review_count
            sku
            stock_status
            price {
                regularPrice {
                    amount {
                        value
                        currency
                    }
                }
            }
            description {
                html
            }
            media_gallery {
                url
            }
        }
    }
}
`;

5. Create Your Product Page In ReactJs:

Inside the src directory, in a file called App.tsx add routing structure:

import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import ProductPage from '../components/ProductPage'; // Your product page component

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/product/:sku" component={ProductPage} />
        {/* Other routes */}
      </Routes>
    </Router>
  );
}

export default App;

6. Create a product page component:

mkdir src/components
touch src/components/ProductPage.tsx

And, add the following code in product page component:

import React, { useEffect, useState } from "react";
import { GET_PRODUCT_BY_SKU } from "../graphql/queries";
import { StarIcon } from "./StarIcon";
import { HeartIcon } from "./Heart";
import { ChartBarIcon } from "./CompareIcon";
import { useParams } from "react-router-dom";
interface ProductType {
  price: any;
  media_gallery: {
    url: string;
  }[];
  name: string;
  stock_status: string;
  sku: string;
  id: string;
}
const ProductPage: React.FC = () => {
  const { sku="" } = useParams<{ sku: string }>();
  const [product, setProduct] = useState<ProductType | null>(null);
  const [loading, setLoading] = useState(true);
  const APP_URL = MAGENTO_ENDPOINT/graphql;
  useEffect(() => {
    const fetchProduct = async () => {
      try {
        const res = await fetch("APP_URL", {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify({
            query: GET_PRODUCT_BY_SKU(sku),
          }),
        });

        const data = await res.json();
        const fetchedProduct = data.data.products.items[0] || null;
        setProduct(fetchedProduct);
      } catch (error) {
        console.error(error);
      } finally {
        setLoading(false);
      }
    };

    fetchProduct();
  }, [sku]);

  if (loading) {
    return <div>Loading...</div>;
  }

  if (!product) {
    return <div>No product found.</div>;
  }

  const priceData = product.price.regularPrice.amount;
  const currency = "USD";
  const value = priceData?.value;
  const price = value?.toLocaleString("en-US", {
    style: "currency",
    currency,
  });
  const items = new Array(5).fill(0);

  return (
       <div className="container relative grid items-start p-3 mx-auto font-sans sm:p-6 lg:grid-cols-12">
      {product.media_gallery && product.media_gallery.length > 0 && (
        <img
          src={product.media_gallery[0].url}
          className="relative object-contain w-screen h-full lg:col-span-7 lg:max-w-4xl aspect-square"
          alt={product.name}
        />
      )}
      <div className="flex flex-col gap-6 mt-5 lg:col-span-5">
        <h1 className="text-4xl lg:text-6xl font-extralight">{product.name}</h1>
        <div className="flex items-center gap-10">
          <div className="flex items-center">
            {items.map((rating) => (
              <StarIcon
                key={rating}
                className={`${3 > rating ? "text-yellow-500 fill-yellow-500" : "text-gray-200"} h-5 w-5 flex-shrink-0`}
                aria-hidden="true"
              />
            ))}
          </div>
          <p className="text-sm font-medium cursor-pointer md:text-base text-sky-600 hover:text-sky-700">{item.review_count} Reviews</p>
          <p className="text-sm font-medium cursor-pointer md:text-base text-sky-600 hover:text-sky-700">Add Your Review</p>
        </div>
        <div className="flex items-start justify-between">
          <h2 className="text-3xl font-medium lg:text-5xl lg:font-semibold">{price}</h2>
          <div>
            <p className="font-semibold">{product?.stock_status?.replace("_", " ")}</p>
            <p>Sku# : {product?.sku}</p>
          </div>
        </div>
        <hr className="w-full h-px border border-gray-200" />
        <div className="flex flex-col gap-px">
          <p className="font-normal">Qty:</p>
          <input
            className="p-2 border border-gray-400 rounded-lg max-w-16"
            defaultValue={1}
            type="number"
            min="1"
            max="100"
          />
        </div>
        <button className="w-full px-8 py-4 text-xl font-semibold text-white duration-200 lg:max-w-60 bg-sky-600 hover:bg-sky-700">
          Add to Cart
        </button>
        <div className="flex items-center gap-12">
          <button className="flex items-center justify-center w-full gap-3 text-sm font-semibold text-gray-500 uppercase cursor-pointer md:text-base max-w-fit">
            <HeartIcon className="w-5 h-5 -mt-px text-gray-500" />
            Add to wishlist
          </button>
          <button className="flex items-center justify-center w-full gap-3 text-sm font-semibold text-gray-500 uppercase cursor-pointer md:text-base max-w-fit">
            <ChartBarIcon className="w-5 h-5 -mt-px fill-gray-500" />
            Add to compare
          </button>
        </div>
      </div>
    </div>
  );
};

export default ProductPage;
react.js product page desktop view
react.js product page mobile view

7. Run Your Application:

Finally, run your ReactJs app to see your product page in action:

npm start

Conclusion

By following these steps, you’ve successfully created a product page using React.Js that integrates seamlessly with your Magento 2 backend.

This foundation not only displays essential product information but also sets the stage for further enhancements.

You can elevate the user experience by adding features such as a customer cart, user reviews, related products, and advanced styling options.

These additions will not only enrich the functionality but also create a more engaging shopping experience for your customers.

Feel free to customize and expand upon this foundation as needed, tailoring it to meet your specific business goals and user needs. The possibilities are endless!

. . .

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