{"id":470451,"date":"2024-10-22T13:15:43","date_gmt":"2024-10-22T13:15:43","guid":{"rendered":"https:\/\/webkul.com\/blog\/?p=470451"},"modified":"2024-10-24T06:00:29","modified_gmt":"2024-10-24T06:00:29","slug":"magento2-reactjs-category-page","status":"publish","type":"post","link":"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/","title":{"rendered":"How to build Magento 2 category page using ReactJS"},"content":{"rendered":"\n<p>Learn how to build a Magento 2 category page using ReactJs in a&nbsp;<a href=\"https:\/\/webkul.com\/headless-commerce-development-services\/\" target=\"_blank\" rel=\"noreferrer noopener\">headless development environment<\/a>.<\/p>\n\n\n\n<p><strong>1.<\/strong> <a href=\"#introduction\">Introduction<\/a><\/p>\n\n\n\n<p><strong>2.<\/strong> <a href=\"#category-set-up\">Setting Up Your Category Page with ReactJs<\/a><\/p>\n\n\n\n<p><strong>3.<\/strong> <a href=\"#category-page-functions\">Creating Your Category Page with ReactJs<\/a><\/p>\n\n\n\n<p><strong>4.<\/strong> <a href=\"#conclusion\">Conclusion<\/a><\/p>\n\n\n\n<p>By leveraging <a href=\"https:\/\/webkul.com\/magento2-headless-development\/\">Magento 2 headless architecture<\/a>, this guide will help you integrate the Magento 2 backend with React.<\/p>\n\n\n\n<p>Unlocking a more flexible and dynamic user experience and harnessing the full potential of <a href=\"https:\/\/webkul.com\/blog\/what-is-headless-ecommerce\/\">headless commerce<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"introduction\">Introduction<\/h2>\n\n\n\n<p>Creating a category page in React for your Magento 2 store can significantly impact user engagement and encourage visitors to explore various product listings.<\/p>\n\n\n\n<p>For a comprehensive guide on setting up product pages, check out our blog, <strong><a href=\"https:\/\/webkul.com\/blog\/magento2-product-page-using-reactjs\/\" target=\"_blank\" rel=\"noreferrer noopener\">How to Create a Magento 2 Product Page in React.<\/a><\/strong><\/p>\n\n\n\n<p>This guide will walk you through building an efficient and user-friendly category page, complete with code examples and detailed explanations. <\/p>\n\n\n\n<p>And, In this blog you are going to know about <a href=\"https:\/\/webkul.com\/magento-2-react-development-services\/\" target=\"_blank\" rel=\"noreferrer noopener\">Magento 2 React Development<\/a>.<\/p>\n\n\n\n<p>You\u2019ll gain valuable insights into <a href=\"https:\/\/webkul.com\/reactjs-development-services\/\" target=\"_blank\" rel=\"noreferrer noopener\">React.js development<\/a>, learning how to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Fetch data from the Magento 2 GraphQL API<\/li>\n\n\n\n<li>Manage application state effectively<\/li>\n\n\n\n<li>Design a responsive layout that enhances the overall shopping experience<\/li>\n<\/ul>\n\n\n\n<p>By the end of this guide, you&#8217;ll have the skills to create a dynamic and engaging category page that elevates your e-commerce platform.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"category-set-up\">Setting Up Your Category Page with ReactJs<\/h2>\n\n\n\n<h4 class=\"wp-block-heading\">1.&nbsp;<strong>Create Your ReactJs Project:<\/strong><\/h4>\n\n\n\n<p>Open your terminal and run the following command to <a href=\"https:\/\/webkul.com\/blog\/create-react-app\/\">create a React.Js<\/a> Project<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">npx create-react-app my-magento-store\ncd my-magento-store<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">2. Navigate to root directory:<\/h4>\n\n\n\n<p><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">cd my-magento-store<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">3. Install Necessary Packages In Your&nbsp;<strong>ReactJs<\/strong>: <\/h4>\n\n\n\n<pre class=\"EnlighterJSRAW\">\/\/As, I created this with Tailwind so:\n\nnpm install -D tailwindcss postcss autoprefixer\nnpx tailwindcss init -p<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"category-page-functions\">Creating Your Category Page with ReactJs<\/h2>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>1. Set Up GraphQL Queries:<\/strong><\/h4>\n\n\n\n<p>As we are using <a href=\"https:\/\/developer.adobe.com\/commerce\/webapi\/graphql\/\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">Magento 2&nbsp;GraphQl<\/a>&nbsp;API. So lets, create a file for your GraphQL queries. This keeps your code organized.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">mkdir src\/graphql\ntouch src\/graphql\/queries.js<\/pre>\n\n\n\n<p><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">export const GET_PRODUCT_BY_CATEGORY = `\n  query(\n  $filter: ProductAttributeFilterInput\n  $pageSize: Int = 12\n  $currentPage: Int = 1\n  $sort: ProductAttributeSortInput\n) {\n  products(\n    filter: $filter\n    pageSize: $pageSize\n    currentPage: $currentPage\n    sort: $sort\n  ) {\n    page_info {\n      current_page\n      page_size\n      total_pages\n    }\n\n    total_count\n    aggregations {\n      attribute_code\n      label\n      count\n      options {\n        count\n        label\n        value\n      }\n    }\n    sort_fields {\n      default\n      options {\n        label\n        value\n      }\n    }\n    items {\n          media_gallery {\n        disabled\n        label\n        url\n        position\n      }\n        \n      review_count\n      rating_summary\n      url_key\n      uid\n      sku\n      name\n\n      thumbnail {\n        id: url\n        url\n        label\n      }\n      price_range {\n        maximum_price {\n          final_price {\n            currency\n            value\n          }\n          regular_price {\n            currency\n            value\n          }\n        }\n        minimum_price {\n          final_price {\n            currency\n            value\n          }\n          regular_price {\n            currency\n            value\n          }\n        }\n      }\n    }\n    suggestions {\n      search\n    }\n  }\n}\n\n`;<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">2. Created a fetch handler in reactjs:<\/h4>\n\n\n\n<p>For reusability created a fetch handler function in file called FetchHandler.ts.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">\/\/ src\/api\/graphql.js\n\nexport const fetchGraphQL = (query, variables) =&gt; {\n  return fetch(&quot;https:\/\/m243.winterroot.com\/graphql&quot;, {\n    method: &quot;POST&quot;,\n    headers: {\n      &quot;Content-Type&quot;: &quot;application\/json&quot;,\n    },\n    body: JSON.stringify({ query, variables }),\n  })\n    .then((response) =&gt; response.json())\n    .then((result) =&gt; {\n      if (result.errors) {\n        throw new Error(result.errors.map((err) =&gt; err.message).join(&quot;, &quot;));\n      }\n      return result.data;\n    });\n};<\/pre>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"1200\" height=\"1021\" src=\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/destop-1200x1021.webp\" alt=\"React Category Page Desktop View\" class=\"wp-image-470480\" srcset=\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/destop-1200x1021.webp 1200w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/destop-300x255.webp 300w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/destop-250x213.webp 250w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/destop-768x653.webp 768w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/destop-1536x1307.webp 1536w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/destop.webp 1694w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" loading=\"lazy\" \/><\/figure>\n\n\n\n<p class=\"has-text-align-center has-small-font-size\" style=\"line-height:.9\"><\/p>\n\n\n\n<div class=\"wp-block-columns wk-bg-radial-gradient is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image size-full is-resized wk-video-mockup-frame\"><img decoding=\"async\" width=\"441\" height=\"831\" src=\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/mobile1.webp\" alt=\"Reactjs Category Page Mobile view 1\" class=\"wp-image-470477\" style=\"object-fit:cover;width:406px;height:auto\" srcset=\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/mobile1.webp 441w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/mobile1-159x300.webp 159w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/mobile1-132x249.webp 132w\" sizes=\"(max-width: 441px) 100vw, 441px\" loading=\"lazy\" \/><\/figure>\n<\/div>\n\n\n\n<div class=\"wp-block-column wk-video-mockup-frame is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image size-full is-resized wk-video-mockup-frame\"><img decoding=\"async\" width=\"441\" height=\"841\" src=\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/mobile3.webp\" alt=\"Reactjs Category Page Mobile view 2\" class=\"wp-image-470479\" style=\"object-fit:cover;width:405px;height:auto\" srcset=\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/mobile3.webp 441w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/mobile3-157x300.webp 157w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/mobile3-131x249.webp 131w\" sizes=\"(max-width: 441px) 100vw, 441px\" loading=\"lazy\" \/><\/figure>\n<\/div>\n<\/div>\n\n\n\n<h4 class=\"wp-block-heading\">3. Render Category Page In Your React Application<\/h4>\n\n\n\n<p>Create Your Category Page Component<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">mkdir src\/components\/category\ntouch src\/components\/category\/index.jsx<\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, add the following code to the <code>index.jsx<\/code> component:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">import { useEffect, useState } from &quot;react&quot;;\nimport SidebarFilter from &quot;.\/SidebarFilter&quot;;\nimport { GET_PRODUCT_BY_CATEGORY } from &quot;..\/..\/graphql\/queries&quot;;\nimport Product from &quot;.\/Product&quot;;\nimport { ArrowDownIcon, ArrowUpIcon, GridView, ListView, XMarkIcon } from &quot;.\/Icons&quot;;\nimport { fetchGraphQL } from &quot;.\/FetchHandler&quot;;\nimport Pagination from &quot;.\/Pagination&quot;;\nimport SelectedList from &quot;.\/SelectedFilter&quot;;\nimport Accordion from &quot;.\/Accordion&quot;;\nexport default function Category() {\n  const &#091;product, setProduct] = useState();\n  const &#091;data, setData] = useState({});\n  const &#091;productView, setProductView] = useState(&quot;grid&quot;);\n  const &#091;filter, setFilter] = useState({});\n  const &#091;loading, setLoading] = useState(true);\n  const &#091;selectedOption, setSelectedOption] = useState(data?.products?.sort_fields.default);\n  const &#091;sort, setSort] = useState({});\n  const &#091;order, setOrder] = useState(&quot;DESC&quot;);\n  const &#091;currentPage, setCurrentPage] = useState(1);\n  const &#091;pageSize, setPageSize] = useState(12);\n  const &#091;openSideBar, setSideBar] = useState(false);\n  const &#091;selectedFilters, setSelectedFilters] = useState(data?.products?.applied_filters || &#091;]);\n  const fetchProduct = async () =&gt; {\n    fetchGraphQL(GET_PRODUCT_BY_CATEGORY, { filter, sort, currentPage, page_size: parseInt(pageSize) })\n      .then((res) =&gt; {\n        setData(res);\n        const fetchedProduct = res.products.items || null;\n        setProduct(fetchedProduct);\n        setLoading(false);\n      })\n      .catch((error) =&gt; {\n        setLoading(false);\n        console.error(&quot;Error fetchin category data:&quot;, error.message);\n      });\n  };\n  const asscendDescend = () =&gt; {\n    if (order === &quot;DESC&quot;) {\n      setOrder(&quot;ASC&quot;);\n    } else {\n      setOrder(&quot;DESC&quot;);\n    }\n  };\n\n  const handleChange = (event) =&gt; {\n    const value = event.target.value;\n    setSelectedOption(value);\n  };\n\n  useEffect(() =&gt; {\n    if (openSideBar) {\n      document.body.classList.add(&quot;overflow-hidden&quot;);\n    } else {\n      document.body.classList.remove(&quot;overflow-hidden&quot;);\n    }\n\n    \/\/ Cleanup to remove class on unmount\n    return () =&gt; {\n      document.body.classList.remove(&quot;overflow-hidden&quot;);\n    };\n  }, &#091;openSideBar]);\n  useEffect(() =&gt; {\n    fetchProduct();\n  }, &#091;filter, sort, order, currentPage, pageSize]);\n  useEffect(() =&gt; {\n    if (selectedOption) {\n      setSort({ &#091;selectedOption]: order });\n    }\n  }, &#091;order, selectedOption]);\n\n  if (loading) {\n    return &lt;div&gt;Loading...&lt;\/div&gt;;\n  }\n  if (!product) {\n    return &lt;div&gt;No product found.&lt;\/div&gt;;\n  }\n\n  const removeFilter = (attributeCode) =&gt; {\n    setSelectedFilters((prev) =&gt; {\n      const { &#091;attributeCode]: _, ...rest } = prev; \/\/ Destructure to remove the specified attribute\n      return rest; \/\/ Return the remaining filters\n    });\n\n    \/\/ Update the filter state to remove the attribute code\n    setFilter((prev) =&gt; {\n      const updatedFilter = { ...prev };\n      delete updatedFilter&#091;attributeCode]; \/\/ Remove the attribute if it&#039;s empty\n      return updatedFilter;\n    });\n  };\n  const resetFilter = () =&gt; {\n    setFilter({});\n    setSelectedFilters(&#091;]);\n  };\n  return (\n    &lt;&gt;\n      &lt;div\n        className={`fixed inset-y-0 lg:hidden right-0 z-10 bg-white w-&#091;99vw] transform ${\n          openSideBar ? &quot;translate-x-0&quot; : &quot;translate-x-full&quot;\n        } transition-transform overflow-y-auto duration-300 pt-5 ease-in-out`}\n      &gt;\n        &lt;SidebarFilter\n          selectedFilters={selectedFilters}\n          resetFilter={resetFilter}\n          removeFilter={removeFilter}\n          aggregations={data?.products?.aggregations}\n          setFilter={setFilter}\n          setSelectedFilters={setSelectedFilters}\n        \/&gt;\n        &lt;button onClick={() =&gt; setSideBar(false)} className=&quot;absolute right-0 p-2 rounded top-7&quot;&gt;\n          &lt;XMarkIcon className=&quot;w-5 h-5 text-slate-500&quot; \/&gt;\n        &lt;\/button&gt;\n      &lt;\/div&gt;\n      &lt;div className=&quot;pb-20&quot;&gt;\n        &lt;div className=&quot;container grid w-full px-4 mx-auto&quot;&gt;\n          &lt;div className=&quot;grid lg:gap-5 lg:grid-cols-4&quot;&gt;\n            &lt;div className=&quot;hidden lg:flex lg:flex-col lg:col-span-1&quot;&gt;\n              &lt;SidebarFilter\n                selectedFilters={selectedFilters}\n                resetFilter={resetFilter}\n                removeFilter={removeFilter}\n                aggregations={data?.products?.aggregations}\n                setFilter={setFilter}\n                setSelectedFilters={setSelectedFilters}\n              \/&gt;\n            &lt;\/div&gt;\n\n            &lt;div className=&quot;flex flex-col lg:col-span-3&quot;&gt;\n              &lt;div className=&quot;flex justify-between px-2 mt-6 md:px-4&quot;&gt;\n                &lt;div className=&quot;items-center hidden gap-2 lg:flex&quot;&gt;\n                  &lt;div className=&quot;flex w-&#091;70px] border border-black&quot;&gt;\n                    &lt;div\n                      onClick={() =&gt; setProductView(&quot;grid&quot;)}\n                      className=&quot; rounded-l-sm border-r border-0 hover:bg-gray-300 cursor-pointer border-x-gray-400 w-10 p-2 px-2  shadow shadow-gray-300\/80 bg-&#091;#efefef] text-gray-600&quot;\n                    &gt;\n                      &lt;GridView \/&gt;\n                    &lt;\/div&gt;\n                    &lt;div\n                      className=&quot;rounded-r-sm w-10 border-0 p-2 px-2 shadow cursor-pointer hover:bg-gray-300 shadow-gray-300\/80 bg-&#091;#efefef] text-gray-600\n&quot;\n                      onClick={() =&gt; setProductView(&quot;list&quot;)}\n                    &gt;\n                      &lt;ListView \/&gt;\n                    &lt;\/div&gt;\n                  &lt;\/div&gt;\n                  &lt;p className=&quot;text-xs&quot;&gt;{data?.products?.total_count} items&lt;\/p&gt;\n                &lt;\/div&gt;\n                &lt;button\n                  className=&quot;flex px-4 py-1 text-sm border border-black lg:hidden bg-neutral-100 max-w-fit&quot;\n                  onClick={() =&gt; setSideBar(true)}\n                &gt;\n                  Shop By\n                &lt;\/button&gt;\n                &lt;div className=&quot;flex items-center gap-2&quot;&gt;\n                  &lt;select\n                    value={selectedOption}\n                    onChange={handleChange}\n                    className=&quot;outline-none py-&#091;6px] text-sm border-black bg-gray-50 placeholder:text-gray-600 placeholder:px-2 border text-gray-900 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-&#091;0_0_3px_1px_#00699d]&quot;\n                  &gt;\n                    &lt;option disabled&gt;{data?.products?.sort_fields.default}&lt;\/option&gt;\n                    {data?.products?.sort_fields.options.map((option) =&gt; (\n                      &lt;option key={option.value} value={option.value}&gt;\n                        {option.label}\n                      &lt;\/option&gt;\n                    ))}\n                  &lt;\/select&gt;\n                  &lt;button onClick={asscendDescend}&gt;\n                    {order === &quot;DESC&quot; ? (\n                      &lt;ArrowDownIcon className=&quot;w-5 h-5 stroke-2 stroke-slate-500&quot; \/&gt;\n                    ) : (\n                      &lt;ArrowUpIcon className=&quot;w-5 h-5 stroke-2 stroke-slate-500&quot; \/&gt;\n                    )}\n                  &lt;\/button&gt;\n                &lt;\/div&gt;\n              &lt;\/div&gt;\n              &lt;div className=&quot;flex flex-col w-full mt-5 lg:hidden&quot;&gt;\n                {Object.entries(filter)?.length &gt; 0 &amp;&amp; (\n                  &lt;div className=&quot;border-t&quot;&gt;\n                    &lt;Accordion title={`Now Shopping by : (${Object.entries(filter)?.length})`}&gt;\n                      &lt;div className=&quot;pt-3 -ml-3&quot;&gt;\n                        &lt;SelectedList\n                          removeFilter={removeFilter}\n                          resetFilter={resetFilter}\n                          selectedFilters={selectedFilters}\n                        \/&gt;\n                      &lt;\/div&gt;\n                    &lt;\/Accordion&gt;\n                  &lt;\/div&gt;\n                )}\n                &lt;p className=&quot;mx-2 my-4 text-xs&quot;&gt;{data?.products?.total_count} items&lt;\/p&gt;\n              &lt;\/div&gt;\n              {\/*  *\/}\n              &lt;div\n                className={`gap-4 ${\n                  productView !== &quot;grid&quot; ? &quot;flex flex-col&quot; : &quot;grid-cols-2 md:grid-cols-3 grid lg:grid-cols-4&quot;\n                }`}\n              &gt;\n                {product?.map((i, index) =&gt; (\n                  &lt;Product productView={productView} key={index} product={i} \/&gt;\n                ))}\n              &lt;\/div&gt;\n              &lt;Pagination\n                data={data}\n                currentPage={currentPage}\n                setCurrentPage={setCurrentPage}\n                setPageSize={setPageSize}\n                pageSize={pageSize}\n              \/&gt;\n            &lt;\/div&gt;\n          &lt;\/div&gt;\n        &lt;\/div&gt;\n      &lt;\/div&gt;\n    &lt;\/&gt;\n  );\n}<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">4. Add Sidebar Filter Component In Your Category Page<\/h4>\n\n\n\n<p>Create the Sidebar Filter Component<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">touch src\/components\/category\/SidebarFilter.jsx<\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p><strong>Implement the Filter Component<\/strong> To promote reusability, create a separate component for the available filter list based on the attributes received from the category list API. <\/p>\n\n\n\n<p>Add the following code to <code>SidebarFilter.jsx<\/code>:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">import Accordion from &quot;.\/Accordion&quot;;\nimport SelectedList from &quot;.\/SelectedFilter&quot;;\n\n\nexport default function SidebarFilter({\n  aggregations,\n  setFilter,\n  setSelectedFilters,\n  selectedFilters,\n  resetFilter,\n  removeFilter,\n}) {\n  const handleFilterChange = (attributeCode, value, label) =&gt; {\n    if (attributeCode) {\n      setSelectedFilters((prev) =&gt; {\n        const currentSelections = prev&#091;attributeCode] || &#091;];\n        const isSelected = currentSelections.includes(value);\n\n        \/\/ Update the selected filters for checkboxes\n        const newSelections =\n          attributeCode === &quot;price&quot;\n            ? &#091;value] \/\/ Only one selection for price\n            : isSelected\n            ? currentSelections.filter((v) =&gt; v !== value) \/\/ Remove if already selected\n            : &#091;...currentSelections, value, label]; \/\/ Add if not selected\n\n        return {\n          ...prev,\n          &#091;attributeCode]: newSelections,\n        };\n      });\n      \/\/ Update the filter state\n      setFilter((prev) =&gt; ({\n        ...prev,\n        &#091;attributeCode]:\n          attributeCode === &quot;price&quot; ? { from: value.split(&quot;_&quot;)?.&#091;0], to: value?.split(&quot;_&quot;)?.&#091;1] } : { eq: value }, \/\/ Use &#039;in&#039; for selected price range\n      }));\n    }\n  };\n\n  return (\n    &lt;div&gt;\n      {Object.entries(selectedFilters)?.length &gt; 0 &amp;&amp; (\n        &lt;div className=&quot;hidden lg:flex&quot;&gt;\n          &lt;SelectedList removeFilter={removeFilter} resetFilter={resetFilter} selectedFilters={selectedFilters} \/&gt;\n        &lt;\/div&gt;\n      )}\n      &lt;p className=&quot;flex p-2 text-2xl font-light border-b lg:text-base lg:font-medium&quot;&gt;Shoping Options&lt;\/p&gt;\n      {aggregations?.map((aggregation, index) =&gt; (\n        &lt;Accordion key={index} title={aggregation.label}&gt;\n          &lt;div className=&quot;flex flex-col gap-2 px-1 py-2&quot;&gt;\n            {aggregation.options.map((option) =&gt; (\n              &lt;div key={option.value}&gt;\n                &lt;label className=&quot;text-sm cursor-pointer&quot;&gt;\n                  &lt;input\n                    className=&quot;hidden&quot;\n                    type=&quot;radio&quot;\n                    value={option.value}\n                    checked={selectedFilters.price === option.value} \/\/ Ensure only one selection for price\n                    onChange={() =&gt; handleFilterChange(aggregation.attribute_code, option.value, option?.label)}\n                  \/&gt;\n                  &lt;span dangerouslySetInnerHTML={{ __html: option?.label }}&gt;&lt;\/span&gt; ({option.count})\n                &lt;\/label&gt;\n              &lt;\/div&gt;\n            ))}\n          &lt;\/div&gt;\n        &lt;\/Accordion&gt;\n      ))}\n    &lt;\/div&gt;\n  );\n}<\/pre>\n\n\n\n<div class=\"wp-block-columns wk-bg-radial-gradient is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow\">\n<h2 class=\"wp-block-heading has-white-color has-text-color has-link-color wp-elements-291b17f6d5d36d859a236dcad35b252e\">Mobile View<\/h2>\n\n\n\n<p class=\"has-white-color has-text-color has-link-color wp-elements-706dd72da4d9ea458fd7250a0b840453\">Filter List In Sidebar<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-column wk-video-mockup-frame is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"456\" height=\"681\" src=\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/sidebar.webp\" alt=\"Reactjs Category Page Mobile view  filtersidebar\" class=\"wp-image-470481\" style=\"object-fit:cover\" srcset=\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/sidebar.webp 456w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/sidebar-201x300.webp 201w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/sidebar-167x249.webp 167w\" sizes=\"(max-width: 456px) 100vw, 456px\" loading=\"lazy\" \/><\/figure>\n<\/div>\n<\/div>\n\n\n\n<h4 class=\"wp-block-heading\">5. Add Selected Filter List Component In Your Category Page<\/h4>\n\n\n\n<p>Create the Selected Filter Component<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">touch src\/components\/category\/SelectedFilter.jsx<\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p><strong>Implement the Selected Filter Component<\/strong> To promote reusability, create a separate component for displaying the selected filters. <\/p>\n\n\n\n<p>This component will include functions for removing filters and rendering the filter list. Add the following code to <code>SelectedFilter.jsx<\/code>:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">import { XMarkIcon } from &quot;.\/Icons&quot;;\n\nconst SelectedList = ({ removeFilter, resetFilter, selectedFilters }) =&gt; {\n  return (\n    &lt;div className=&quot;flex flex-col px-2&quot;&gt;\n      &lt;p className=&quot;hidden pb-5 text-base font-medium lg:flex&quot;&gt;Now Shopping by&lt;\/p&gt;\n      &lt;ul&gt;\n        {Object.entries(selectedFilters).map((&#091;attributeCode, options]) =&gt; (\n          &lt;li key={attributeCode} className=&quot;flex items-center text-sm gap-0.5&quot;&gt;\n            &lt;button onClick={() =&gt; options.forEach((option) =&gt; removeFilter(attributeCode, option))}&gt;\n              &lt;XMarkIcon className=&quot;w-5 h-5 text-slate-500&quot; \/&gt;\n            &lt;\/button&gt;\n            &lt;span className=&quot;font-semibold capitalize cursor-pointer&quot;&gt;{attributeCode.replace(&quot;_&quot;, &quot; &quot;)}&lt;\/span&gt;:{&quot; &quot;}\n            {options.length &gt; 1 ? options&#091;1] : options&#091;0].replace(&quot;_&quot;, &quot; - &quot;)}{&quot; &quot;}\n          &lt;\/li&gt;\n        ))}\n        &lt;li className=&quot;mt-5 text-sm cursor-pointer mb-7 text-sky-600&quot; onClick={resetFilter}&gt;\n          Clear All\n        &lt;\/li&gt;\n      &lt;\/ul&gt;\n    &lt;\/div&gt;\n  );\n};\nexport default SelectedList;<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">6. Add Pagination In Your Category Page<\/h4>\n\n\n\n<p>Create the Pagination Component<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">touch src\/components\/category\/Pagination.jsx<\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p><strong>Implement the Pagination Component<\/strong> To incorporate pagination and page size functionality, add the following code to <code>Pagination.jsx<\/code>:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">import React from &quot;react&quot;;\nimport { ChevronDownIcon } from &quot;.\/Icons&quot;;\n\nexport default function Pagination({ data, currentPage, setCurrentPage, setPageSize, pageSize }) {\n  const productCounts = Array.from(\n    { length: Math.floor(data?.products?.total_count \/ 12) + 1 },\n    (_, index) =&gt; index * 12\n  );\n  const handleChangePageSize = (event) =&gt; {\n    const value = event.target.value;\n    setPageSize(value);\n  };\n  const handlePageChange = (page) =&gt; {\n    setCurrentPage(page);\n  };\n\n  const getPageNumbers = () =&gt; {\n    const pages = &#091;];\n    const maxVisiblePages = 5;\n\n    \/\/ Determine the range of pages to display\n    let startPage = Math.max(1, currentPage - Math.floor(maxVisiblePages \/ 2));\n    let endPage = Math.min(data?.products?.page_info?.total_pages, startPage + maxVisiblePages - 1);\n\n    \/\/ Adjust startPage if there are not enough pages before\n    if (endPage - startPage &lt; maxVisiblePages - 1) {\n      startPage = Math.max(1, endPage - maxVisiblePages + 1);\n    }\n\n    \/\/ Build the array of page numbers\n    for (let i = startPage; i &lt;= endPage; i++) {\n      pages.push(i);\n    }\n\n    return pages;\n  };\n  return (\n    data?.products?.page_info?.total_pages &gt; 1 &amp;&amp; (\n      &lt;div className=&quot;flex items-center justify-between w-full&quot;&gt;\n        &lt;div className=&quot;flex justify-center space-x-2&quot;&gt;\n          {\/* Previous button *\/}\n          {currentPage &gt; 1 &amp;&amp; (\n            &lt;button\n              onClick={() =&gt; handlePageChange(currentPage - 1)}\n              className=&quot;px-2 py-1 text-black bg-gray-300 rounded&quot;\n            &gt;\n              &lt;ChevronDownIcon className=&quot;w-5 h-5 rotate-90 text-slate-500&quot; \/&gt;\n            &lt;\/button&gt;\n          )}\n          {getPageNumbers().map((page) =&gt; (\n            &lt;button\n              key={page}\n              onClick={() =&gt; handlePageChange(page)}\n              className={`p-1 rounded text-center text-xs ${\n                currentPage === page ? &quot;bg-neutral-200 text-black&quot; : &quot;text-sky-800&quot;\n              }`}\n            &gt;\n              {page}\n            &lt;\/button&gt;\n          ))}\n\n          {\/* Next button *\/}\n          {currentPage &lt; data?.products?.page_info?.total_pages &amp;&amp; (\n            &lt;button\n              onClick={() =&gt; handlePageChange(currentPage + 1)}\n              className=&quot;px-2 py-1 text-black bg-gray-300 rounded&quot;\n            &gt;\n              &lt;ChevronDownIcon className=&quot;w-5 h-5 -rotate-90 text-slate-500&quot; \/&gt;\n            &lt;\/button&gt;\n          )}\n        &lt;\/div&gt;\n        &lt;select\n          value={pageSize}\n          onChange={handleChangePageSize}\n          className=&quot;outline-none max-w-fit py-&#091;6px] px-4 text-sm bg-gray-50 placeholder:text-gray-600 placeholder:px-2 border border-gray-300 text-gray-900 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-&#091;0_0_3px_1px_#00699d]&quot;\n        &gt;\n          &lt;option disabled&gt;{data?.products?.sort_fields.default}&lt;\/option&gt;\n          {productCounts.map((option) =&gt; (\n            &lt;option key={option} value={option}&gt;\n              {option}\n            &lt;\/option&gt;\n          ))}\n        &lt;\/select&gt;\n      &lt;\/div&gt;\n    )\n  );\n}<\/pre>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"1200\" height=\"527\" src=\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/pagination-1200x527.webp\" alt=\"Category Page pagination\" class=\"wp-image-470483\" srcset=\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/pagination-1200x527.webp 1200w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/pagination-300x132.webp 300w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/pagination-250x110.webp 250w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/pagination-768x337.webp 768w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/pagination-1536x675.webp 1536w, https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/pagination.webp 1644w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" loading=\"lazy\" \/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">7. Create Product Card Component<\/h4>\n\n\n\n<p>Create A Product Card Component Component For Category Items<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">touch src\/components\/category\/Product.jsx<\/pre>\n\n\n\n<p><strong>Implement the Product Card Component<\/strong> To promote reusability, create a separate component for the product card structure that will be rendered in the category listing. <\/p>\n\n\n\n<p>Add the following code to <code>Product.jsx<\/code>:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">import { ChartBarIcon, HeartIcon, StarIcon } from &quot;.\/Icons&quot;;\n\nconst Product = ({ product, productView }) =&gt; {\n  const priceData = product?.price_range?.maximum_price?.final_price;\n  const currency = &quot;USD&quot;;\n  const value = priceData?.value;\n  const price = value?.toLocaleString(&quot;en-US&quot;, {\n    style: &quot;currency&quot;,\n    currency,\n  });\n  const listType = productView !== &quot;grid&quot;;\n  return (\n    &lt;div className=&quot;group&quot;&gt;\n      &lt;div className={`relative flex ${listType ? &quot;flex-row&quot; : &quot;flex-col&quot;} w-full overflow-hidden bg-white rounded-lg`}&gt;\n        &lt;div className=&quot;relative grid object-cover mx-3 mt-3 overflow-hidden aspect-square h-60 rounded-xl&quot;&gt;\n          &lt;img className=&quot;object-cover aspect-square&quot; src={product.media_gallery?.at(0).url} alt={product.name} \/&gt;\n        &lt;\/div&gt;\n        &lt;div className=&quot;px-5 pb-5 mt-4&quot;&gt;\n          &lt;h5 className=&quot;text-xl tracking-tight text-slate-900&quot;&gt;\n            {&quot; &quot;}\n            &lt;span dangerouslySetInnerHTML={{ __html: product?.name }}&gt;&lt;\/span&gt;\n          &lt;\/h5&gt;\n          &lt;div className=&quot;flex items-center gap-2&quot;&gt;\n            {product?.review_count &gt; 0 &amp;&amp; (\n              &lt;div className=&quot;flex items-center&quot;&gt;\n                {Array.from({ length: 5 }, (_, index) =&gt; {\n                  const ratingValue = index + 1;\n                  const isFilled = ratingValue &lt;= product.rating_summary \/ 20; \/\/ Assuming rating_summary is out of 100\n\n                  return &lt;StarIcon index={index} isFilled={isFilled} \/&gt;;\n                })}\n                &lt;span className=&quot;rounded text-sky-600 px-2.5 py-0.5 text-xs font-normal&quot;&gt;\n                  {product?.review_count} Reviews\n                &lt;\/span&gt;\n              &lt;\/div&gt;\n            )}\n          &lt;\/div&gt;\n          &lt;div className=&quot;flex items-center justify-between mt-2 mb-5&quot;&gt;\n            &lt;p&gt;\n              &lt;span className=&quot;font-bold text-md text-slate-900&quot;&gt;{price}&lt;\/span&gt;\n            &lt;\/p&gt;\n          &lt;\/div&gt;\n          &lt;div className={`items-center gap-2  ${listType ? &quot;flex&quot; : &quot;hidden group-hover:flex&quot;}`}&gt;\n            &lt;button className=&quot;w-full px-4 py-2 my-6 font-medium text-white max-w-fit bg-sky-600 hover:bg-sky-700&quot;&gt;\n              Add to cart\n            &lt;\/button&gt;\n            &lt;HeartIcon className=&quot;w-5 h-5 text-slate-500&quot; \/&gt;\n            &lt;ChartBarIcon className=&quot;w-5 h-5 text-slate-500&quot; \/&gt;\n          &lt;\/div&gt;\n          {listType &amp;&amp; &lt;p className=&quot;text-sm text-sky-600&quot;&gt;Learn More&lt;\/p&gt;}\n        &lt;\/div&gt;\n      &lt;\/div&gt;\n    &lt;\/div&gt;\n  );\n};\nexport default Product;<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">8. Add Accordion Component For Your Category Page<\/h4>\n\n\n\n<p>Create Accordion Component<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">touch src\/components\/category\/Accordion.jsx<\/pre>\n\n\n\n<p><strong>Implement the Accordion Component<\/strong> To promote reusability, create a separate component for the accordion, which will be used to render various types of filter lists. <\/p>\n\n\n\n<p>Add the following code to <code>Accordion.jsx<\/code>:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">import { useState } from &quot;react&quot;;\nimport { ChevronDownIcon, ChevronUpIcon } from &quot;.\/Icons&quot;;\n\nconst Accordion = ({ children, title }) =&gt; {\n    const &#091;open, setOpen] =useState(false);\n    return (\n      &lt;&gt;\n        &lt;div className=&quot;w-full p-2 border border-t-0 border-l-0 border-r-0&quot;&gt;\n          &lt;div onClick={() =&gt; setOpen(!open)} className=&quot;flex items-center justify-between w-full cursor-pointer&quot;&gt;\n            &lt;div className=&quot;text-base font-medium capitalize&quot;&gt;{title}&lt;\/div&gt;\n            &lt;div className=&quot;text-base&quot;&gt;\n              {open ? (\n                &lt;span&gt;\n                  &lt;ChevronUpIcon className=&quot;w-5 h-5 text-slate-500&quot; \/&gt;\n                &lt;\/span&gt;\n              ) : (\n                &lt;span&gt;\n                  &lt;ChevronDownIcon className=&quot;w-5 h-5 text-slate-500&quot; \/&gt;\n                &lt;\/span&gt;\n              )}\n            &lt;\/div&gt;\n          &lt;\/div&gt;\n          {open &amp;&amp; children}\n        &lt;\/div&gt;\n      &lt;\/&gt;\n    );\n  };\n  export default Accordion;<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">9. Update App.jsx Component Of Your React Project<\/h4>\n\n\n\n<p>To ensure your React application effectively utilizes the new components you&#8217;ve created for the category page, <\/p>\n\n\n\n<p>it\u2019s essential to update the <code>App.jsx<\/code> component. This update will involve integrating the header and the category page into a cohesive layout.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">import &quot;.\/App.css&quot;;\nimport Category from &quot;.\/components\/category\/Index&quot;;\nimport Header &quot;.\/components\/Header&quot;;\nfunction App() {\n  return (\n    &lt;&gt;\n      &lt;Header \/&gt;\n      &lt;Category \/&gt;\n    &lt;\/&gt;\n  );\n}\n\nexport default App;<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">10. <strong>Run Your ReactJs Application:<\/strong><\/h4>\n\n\n\n<p>Finally, run your <a href=\"https:\/\/react.dev\/\" target=\"_blank\" rel=\"noreferrer noopener\">React.Js<\/a> app to see your category page in action:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\">npm start<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"conclusion\">Conclusion<\/h2>\n\n\n\n<p>In this blog, we explored how to create a robust shopping category page using React in conjunction with the Magento API.<\/p>\n\n\n\n<p>We covered essential functionalities, including sorting options, pagination, and dynamic filters that respond to user interactions.<\/p>\n\n\n\n<p><strong>Key Takeaways:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>State Management<\/strong>: Leveraging React&#8217;s state hooks to manage category data ensures a seamless user experience.<\/li>\n\n\n\n<li><strong>GraphQL Integration<\/strong>: Utilizing the <a href=\"https:\/\/webkul.com\/blog\/graphql-implementation-in-magento2\/\" target=\"_blank\" rel=\"noreferrer noopener\">Magento 2 GraphQL API<\/a> for fetching and displaying category information allows for efficient data handling and flexibility in managing category operations.<\/li>\n<\/ul>\n\n\n\n<p>By following these principles and utilizing the components we&#8217;ve discussed, developers can create an engaging and efficient product listing experience. <\/p>\n\n\n\n<p>That integrates smoothly with Magento 2&#8217;s powerful e-commerce capabilities.<\/p>\n\n\n\n<p>With this foundation, you can further enhance features, improve performance, and refine the user interface to meet your specific business needs.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Learn how to build a Magento 2 category page using ReactJs in a&nbsp;headless development environment. 1. Introduction 2. Setting Up Your Category Page with ReactJs 3. Creating Your Category Page with ReactJs 4. Conclusion By leveraging Magento 2 headless architecture, this guide will help you integrate the Magento 2 backend with React. Unlocking a more <a href=\"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/\">[&#8230;]<\/a><\/p>\n","protected":false},"author":496,"featured_media":470852,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[78,198,9121,6357],"tags":[2064,2070,7895,6360,6359,13578,590],"class_list":["post-470451","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-css3","category-javascript","category-magento-2","category-react-js","tag-javascript","tag-magento2","tag-react","tag-react-ecommerce","tag-react-js","tag-tailwindcss","tag-webkul"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>ReactJs | How to build Magento 2 category page using ReactJS - Webkul Blog<\/title>\n<meta name=\"description\" content=\"Create a dynamic Magento 2 category page with ReactJs and GraphQL. Follow this guide for setup, data fetching, and styling tips.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"ReactJs | How to build Magento 2 category page using ReactJS - Webkul Blog\" \/>\n<meta property=\"og:description\" content=\"Create a dynamic Magento 2 category page with ReactJs and GraphQL. Follow this guide for setup, data fetching, and styling tips.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/\" \/>\n<meta property=\"og:site_name\" content=\"Webkul Blog\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/webkul\/\" \/>\n<meta property=\"article:published_time\" content=\"2024-10-22T13:15:43+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-10-24T06:00:29+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/destop-3.webp\" \/>\n\t<meta property=\"og:image:width\" content=\"1694\" \/>\n\t<meta property=\"og:image:height\" content=\"1441\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/webp\" \/>\n<meta name=\"author\" content=\"Arun Tiwari\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@webkul\" \/>\n<meta name=\"twitter:site\" content=\"@webkul\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Arun Tiwari\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/\"},\"author\":{\"name\":\"Arun Tiwari\",\"@id\":\"https:\/\/webkul.com\/blog\/#\/schema\/person\/b3d968b3f55f433fda5b0d660dbea4aa\"},\"headline\":\"How to build Magento 2 category page using ReactJS\",\"datePublished\":\"2024-10-22T13:15:43+00:00\",\"dateModified\":\"2024-10-24T06:00:29+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/\"},\"wordCount\":714,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/webkul.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/destop-3.webp\",\"keywords\":[\"JavaScript\",\"Magento2\",\"react\",\"react ecommerce\",\"react js\",\"TailwindCss\",\"webkul\"],\"articleSection\":[\"CSS3\",\"JavaScript\",\"Magento 2\",\"react js\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/\",\"url\":\"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/\",\"name\":\"ReactJs | How to build Magento 2 category page using ReactJS - Webkul Blog\",\"isPartOf\":{\"@id\":\"https:\/\/webkul.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/destop-3.webp\",\"datePublished\":\"2024-10-22T13:15:43+00:00\",\"dateModified\":\"2024-10-24T06:00:29+00:00\",\"description\":\"Create a dynamic Magento 2 category page with ReactJs and GraphQL. Follow this guide for setup, data fetching, and styling tips.\",\"breadcrumb\":{\"@id\":\"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/#primaryimage\",\"url\":\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/destop-3.webp\",\"contentUrl\":\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/destop-3.webp\",\"width\":1694,\"height\":1441,\"caption\":\"Magento 2 reactjs category page\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/webkul.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"How to build Magento 2 category page using ReactJS\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/webkul.com\/blog\/#website\",\"url\":\"https:\/\/webkul.com\/blog\/\",\"name\":\"Webkul Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/webkul.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/webkul.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/webkul.com\/blog\/#organization\",\"name\":\"WebKul Software Private Limited\",\"url\":\"https:\/\/webkul.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/webkul.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2021\/08\/webkul-logo-accent-sq.png\",\"contentUrl\":\"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2021\/08\/webkul-logo-accent-sq.png\",\"width\":380,\"height\":380,\"caption\":\"WebKul Software Private Limited\"},\"image\":{\"@id\":\"https:\/\/webkul.com\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/webkul\/\",\"https:\/\/x.com\/webkul\",\"https:\/\/www.instagram.com\/webkul\/\",\"https:\/\/www.linkedin.com\/company\/webkul\",\"https:\/\/www.youtube.com\/user\/webkul\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/webkul.com\/blog\/#\/schema\/person\/b3d968b3f55f433fda5b0d660dbea4aa\",\"name\":\"Arun Tiwari\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/webkul.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/07faf0906e0520912140e99abd63bf5620be60c11bb1220fe25dacda8a9f4896?s=96&d=https%3A%2F%2Fcdnblog.webkul.com%2Fblog%2Fwp-content%2Fuploads%2F2019%2F10%2Fmike.png&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/07faf0906e0520912140e99abd63bf5620be60c11bb1220fe25dacda8a9f4896?s=96&d=https%3A%2F%2Fcdnblog.webkul.com%2Fblog%2Fwp-content%2Fuploads%2F2019%2F10%2Fmike.png&r=g\",\"caption\":\"Arun Tiwari\"},\"description\":\"Arun Tiwari, a skilled Software Engineer, specializes in making Magento Headless compatible extensions. With deep expertise in headless architecture, Arun crafts seamless, scalable solutions.\",\"url\":\"https:\/\/webkul.com\/blog\/author\/aruntiwari-mg565\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"ReactJs | How to build Magento 2 category page using ReactJS - Webkul Blog","description":"Create a dynamic Magento 2 category page with ReactJs and GraphQL. Follow this guide for setup, data fetching, and styling tips.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/","og_locale":"en_US","og_type":"article","og_title":"ReactJs | How to build Magento 2 category page using ReactJS - Webkul Blog","og_description":"Create a dynamic Magento 2 category page with ReactJs and GraphQL. Follow this guide for setup, data fetching, and styling tips.","og_url":"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/","og_site_name":"Webkul Blog","article_publisher":"https:\/\/www.facebook.com\/webkul\/","article_published_time":"2024-10-22T13:15:43+00:00","article_modified_time":"2024-10-24T06:00:29+00:00","og_image":[{"width":1694,"height":1441,"url":"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/destop-3.webp","type":"image\/webp"}],"author":"Arun Tiwari","twitter_card":"summary_large_image","twitter_creator":"@webkul","twitter_site":"@webkul","twitter_misc":{"Written by":"Arun Tiwari","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/#article","isPartOf":{"@id":"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/"},"author":{"name":"Arun Tiwari","@id":"https:\/\/webkul.com\/blog\/#\/schema\/person\/b3d968b3f55f433fda5b0d660dbea4aa"},"headline":"How to build Magento 2 category page using ReactJS","datePublished":"2024-10-22T13:15:43+00:00","dateModified":"2024-10-24T06:00:29+00:00","mainEntityOfPage":{"@id":"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/"},"wordCount":714,"commentCount":0,"publisher":{"@id":"https:\/\/webkul.com\/blog\/#organization"},"image":{"@id":"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/#primaryimage"},"thumbnailUrl":"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/destop-3.webp","keywords":["JavaScript","Magento2","react","react ecommerce","react js","TailwindCss","webkul"],"articleSection":["CSS3","JavaScript","Magento 2","react js"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/","url":"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/","name":"ReactJs | How to build Magento 2 category page using ReactJS - Webkul Blog","isPartOf":{"@id":"https:\/\/webkul.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/#primaryimage"},"image":{"@id":"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/#primaryimage"},"thumbnailUrl":"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/destop-3.webp","datePublished":"2024-10-22T13:15:43+00:00","dateModified":"2024-10-24T06:00:29+00:00","description":"Create a dynamic Magento 2 category page with ReactJs and GraphQL. Follow this guide for setup, data fetching, and styling tips.","breadcrumb":{"@id":"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/#primaryimage","url":"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/destop-3.webp","contentUrl":"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2024\/10\/destop-3.webp","width":1694,"height":1441,"caption":"Magento 2 reactjs category page"},{"@type":"BreadcrumbList","@id":"https:\/\/webkul.com\/blog\/magento2-reactjs-category-page\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/webkul.com\/blog\/"},{"@type":"ListItem","position":2,"name":"How to build Magento 2 category page using ReactJS"}]},{"@type":"WebSite","@id":"https:\/\/webkul.com\/blog\/#website","url":"https:\/\/webkul.com\/blog\/","name":"Webkul Blog","description":"","publisher":{"@id":"https:\/\/webkul.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/webkul.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/webkul.com\/blog\/#organization","name":"WebKul Software Private Limited","url":"https:\/\/webkul.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/webkul.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2021\/08\/webkul-logo-accent-sq.png","contentUrl":"https:\/\/cdnblog.webkul.com\/blog\/wp-content\/uploads\/2021\/08\/webkul-logo-accent-sq.png","width":380,"height":380,"caption":"WebKul Software Private Limited"},"image":{"@id":"https:\/\/webkul.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/webkul\/","https:\/\/x.com\/webkul","https:\/\/www.instagram.com\/webkul\/","https:\/\/www.linkedin.com\/company\/webkul","https:\/\/www.youtube.com\/user\/webkul\/"]},{"@type":"Person","@id":"https:\/\/webkul.com\/blog\/#\/schema\/person\/b3d968b3f55f433fda5b0d660dbea4aa","name":"Arun Tiwari","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/webkul.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/07faf0906e0520912140e99abd63bf5620be60c11bb1220fe25dacda8a9f4896?s=96&d=https%3A%2F%2Fcdnblog.webkul.com%2Fblog%2Fwp-content%2Fuploads%2F2019%2F10%2Fmike.png&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/07faf0906e0520912140e99abd63bf5620be60c11bb1220fe25dacda8a9f4896?s=96&d=https%3A%2F%2Fcdnblog.webkul.com%2Fblog%2Fwp-content%2Fuploads%2F2019%2F10%2Fmike.png&r=g","caption":"Arun Tiwari"},"description":"Arun Tiwari, a skilled Software Engineer, specializes in making Magento Headless compatible extensions. With deep expertise in headless architecture, Arun crafts seamless, scalable solutions.","url":"https:\/\/webkul.com\/blog\/author\/aruntiwari-mg565\/"}]}},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/webkul.com\/blog\/wp-json\/wp\/v2\/posts\/470451","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/webkul.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/webkul.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/webkul.com\/blog\/wp-json\/wp\/v2\/users\/496"}],"replies":[{"embeddable":true,"href":"https:\/\/webkul.com\/blog\/wp-json\/wp\/v2\/comments?post=470451"}],"version-history":[{"count":19,"href":"https:\/\/webkul.com\/blog\/wp-json\/wp\/v2\/posts\/470451\/revisions"}],"predecessor-version":[{"id":471036,"href":"https:\/\/webkul.com\/blog\/wp-json\/wp\/v2\/posts\/470451\/revisions\/471036"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/webkul.com\/blog\/wp-json\/wp\/v2\/media\/470852"}],"wp:attachment":[{"href":"https:\/\/webkul.com\/blog\/wp-json\/wp\/v2\/media?parent=470451"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/webkul.com\/blog\/wp-json\/wp\/v2\/categories?post=470451"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/webkul.com\/blog\/wp-json\/wp\/v2\/tags?post=470451"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}