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
- Create Your ReactJs Project
- Navigate to root directory
- Install Necessary Packages In Your ReactJs
- Set Up GraphQL Queries
- Create Your Product Page In ReactJs
- Create a product page component
- Run Your Application
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.
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.
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
2. Navigate to root directory:
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;
Mobile View
Product details in 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!
Be the first to comment.