{"id":28022,"date":"2021-06-02T08:57:57","date_gmt":"2021-06-02T08:57:57","guid":{"rendered":"http:\/\/How-To-Build-an-Ecommerce-App-With-React"},"modified":"2021-06-02T08:57:57","modified_gmt":"2021-06-02T08:57:57","slug":"how-to-build-an-ecommerce-app-with-react","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/","title":{"rendered":"How To Build an Ecommerce App With React"},"content":{"rendered":"<div class=\"wp-block-cloudinary-markdown \"><p>In this media jam, we will discuss how to build an ecommerce app in <a href=\"https:\/\/reactjs.org\/\">React<\/a> using <a href=\"https:\/\/airtable.com\/\">Airtable<\/a>, <a href=\"https:\/\/cloudinary.com\/\">Cloudinary<\/a> and <a href=\"https:\/\/snipcart.com\/\">Snipcart<\/a>.<\/p>\n<p>We will use Airtable to store product data and use Cloudinary\u2019s Product Gallery to showcase different product images. In this tutorial, we will build an ecommerce site for a cake shop named <strong>Sweet Tooth<\/strong> and use various cakes as products.<\/p>\n<p>If you want to jump right into the code, check out the <a href=\"https:\/\/github.com\/lelouchB\/react-ecommerce-app\">GitHub Repo here<\/a>.<\/p>\n<h2>CodeSandbox<\/h2>\n<\/div>\n  \n  <div class=\"wp-block-cloudinary-code-sandbox \">\n    <iframe\n      src=\"https:\/\/codesandbox.io\/embed\/react-ecommerce-app-4jhlr?theme=dark&amp;codemirror=1&amp;highlights=&amp;editorsize=50&amp;fontsize=14&amp;expanddevtools=0&amp;hidedevtools=0&amp;eslint=0&amp;forcerefresh=0&amp;hidenavigation=0&amp;initialpath=%2F&amp;module=%2Fsrc%2FApp.js&amp;moduleview=0&amp;previewwindow=&amp;view=&amp;runonclick=1\"\n      height=\"500\"\n      style=\"width: 100%;\"\n      title=\"react-ecommerce-app\"\n      loading=\"lazy\"\n      allow=\"accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking\"\n      sandbox=\"allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts\"\n    ><\/iframe>\n  <\/div>\n\n  <div class=\"wp-block-cloudinary-markdown \"><h2>Setup<\/h2>\n<p>Run the following command to create the initial React app with <a href=\"https:\/\/create-react-app.dev\/\">CRA<\/a> (<code>create-react-app<\/code>) template.<\/p>\n<pre class=\"js-syntax-highlighted\"><span><code class=\"hljs shcb-wrap-lines\">npx create-react-app react-ecommerce-app\ncd react-ecommerce-app\nnpm start\n<\/code><\/span><\/pre>\n<p>The last command, <code>npm start<\/code>, will start the development server on your system\u2019s port 3000. You can stop the server by hitting <strong>CTRL+C<\/strong> in the terminal.<\/p>\n<p>The next step is to install the dependencies that you will need in this project. Run the following command to install them.<\/p>\n<pre class=\"js-syntax-highlighted\"><span><code class=\"hljs shcb-wrap-lines\">npm i airtable cloudinary-react \n<\/code><\/span><\/pre>\n<p>In this project, you will use <a href=\"https:\/\/tailwindcss.com\/\">Tailwind CSS<\/a> to style the ecommerce app. Its installation and configuration are beyond the scope of this media jam; you can refer to the <a href=\"https:\/\/tailwindcss.com\/docs\/guides\/create-react-app\">official documentation to install Tailwind CSS<\/a> before proceeding further.<\/p>\n<p>Run the following command to create a file named <code>.env<\/code> to store your API keys securely.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\"><span class=\"hljs-selector-tag\">touch<\/span> <span class=\"hljs-selector-class\">.env<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Head over to <a href=\"https:\/\/app.snipcart.com\/register\">https:\/\/app.snipcart.com\/register<\/a> in your browser and create a free account on Snipcart.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/jesse-thisdot\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/v1622101540\/e-603fc45fe6c0b4006873802f\/pxv49wa41k0bf8dwumqq.png\" alt=\"Snipcart Homepage\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1898\" height=\"908\"\/><\/p>\n<p>After creating the Snipcart account, head over to <a href=\"https:\/\/app.snipcart.com\/?ReturnUrl=%2fdashboard%2faccount%2fcredentials\">account settings<\/a> and copy the <strong>PUBLIC TEST API KEY<\/strong> under Credentials.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/jesse-thisdot\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/v1622101599\/e-603fc45fe6c0b4006873802f\/n7rtb1kwc16nwjhtddhf.png\" alt=\"PUBLIC TEST API KEY\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1898\" height=\"908\"\/><\/p>\n<p>Login into your <a href=\"https:\/\/cloudinary.com\/\">https:\/\/cloudinary.com\/<\/a> and copy the <strong>Cloud Name<\/strong> from your dashboard. All the product images will be stored in Cloudinary.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/jesse-thisdot\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/v1622101648\/e-603fc45fe6c0b4006873802f\/g0m4bvjnnmb3gbu2lkcn.png\" alt=\"Cloudinary Dashboard\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1438\" height=\"316\"\/><\/p>\n<p>Create a folder named <code>sweet-tooth<\/code> in your Cloudinary account and upload Butter Cake\u2019s image into it. You can download the image from <a href=\"https:\/\/res.cloudinary.com\/singhashutoshk\/image\/upload\/v1621864433\/sweet-tooth\/daqzgdkjuby72nk4rrdg.jpg\">here<\/a>. After uploading the image, copy its <code>public_id<\/code>.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/jesse-thisdot\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/v1622102440\/e-603fc45fe6c0b4006873802f\/jfmphsefhtqviy0pfyke.jpg\" alt=\"Butter Cake\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1200\" height=\"1200\"\/><\/p>\n<p>You will use Airtable to store the product\u2019s data. <a href=\"https:\/\/tailwindcss.com\/docs\/guides\/create-react-app\">Create an account on Airtable<\/a> if you haven\u2019t already.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/jesse-thisdot\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/v1622101701\/e-603fc45fe6c0b4006873802f\/xra8kejxvbb215ap2m6w.png\" alt=\"Airtable\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1898\" height=\"908\"\/><\/p>\n<p>Every product will at least have the following fields:<\/p>\n<ul>\n<li>\n<code>id<\/code> &#8211; Unique ID of the product. &#8211; <code>Number<\/code>\n<\/li>\n<li>\n<code>name<\/code> &#8211; Name of the product. &#8211; <code>Single Line Text<\/code>\n<\/li>\n<li>\n<code>description<\/code> &#8211; Short description of the product. &#8211; <code>Long Text<\/code>\n<\/li>\n<li>\n<code>price<\/code> &#8211; Price of the product. &#8211; <code>Currency<\/code>\n<\/li>\n<li>\n<code>public_id<\/code> &#8211; Public Id of product\u2019s image copied from Cloudinary. &#8211; <code>Single Line Text<\/code>\n<\/li>\n<\/ul>\n<p>You can add more fields like <code>stock<\/code>, <code>ratings<\/code>, <code>feedback<\/code>, etc. if you want.<\/p>\n<p>Create a workspace named <strong>Sweet Tooth<\/strong> in Airtable and a base named <code>cakes<\/code> inside the Sweet Tooth workspace. Add the following data of <strong>Butter Cake<\/strong> to it.<\/p>\n<ul>\n<li>\n<code>id<\/code> &#8211; 1<\/li>\n<li>\n<code>name<\/code> &#8211; Butter Cake<\/li>\n<li>\n<code>description<\/code> &#8211; A butter cake is a cake in which one of the main ingredients is butter.<\/li>\n<li>\n<code>price<\/code> &#8211; $30.00<\/li>\n<li>\n<code>public_id<\/code> &#8211; sweet-tooth\/{YOUR-PRODUCT\u2019S-PUBLIC-ID}<\/li>\n<\/ul>\n<p><strong>You can copy the data used in this project from <a href=\"https:\/\/airtable.com\/shre2MWIyxJgAepfC\">https:\/\/airtable.com\/shre2MWIyxJgAepfC<\/a>.<\/strong><\/p>\n<p>After adding the record for Butter Cake, head over to <a href=\"https:\/\/airtable.com\/api\">https:\/\/airtable.com\/api<\/a> and select the base you just created, i.e., <strong>Sweet Tooth, c<\/strong>opy the base\u2019s id from the introduction section.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/jesse-thisdot\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/v1622101745\/e-603fc45fe6c0b4006873802f\/xvltmormevka0ommpi9h.png\" alt=\"Airtable Base ID\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1920\" height=\"908\"\/><\/p>\n<p>Navigate to <a href=\"https:\/\/airtable.com\/account\">https:\/\/airtable.com\/account<\/a> and copy your <strong>Airtable API Key<\/strong>.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/jesse-thisdot\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/v1622101771\/e-603fc45fe6c0b4006873802f\/pchdl8z8b6qsfqv2tdw8.png\" alt=\"Airtable API Key\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1438\" height=\"292\"\/><\/p>\n<p>Paste all the API Keys in the <code>.env<\/code> file.<\/p>\n<pre class=\"js-syntax-highlighted\"><code>REACT_APP_CLOUDINARY_CLOUD_NAME =''\nREACT_APP_AIRTABLE_BASE_ID = ''\nREACT_APP_AIRTABLE_API_KEY =''\nREACT_APP_SNIPCART_KEY=''\n<\/code><\/pre>\n<p>Update your <code>index.html<\/code> to include Cloudinary\u2019s Product Gallery JavaScript file and Snipcart\u2019s  CSS and JavaScript like this.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-meta\">&lt;!DOCTYPE <span class=\"hljs-meta-keyword\">html<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">html<\/span> <span class=\"hljs-attr\">lang<\/span>=<span class=\"hljs-string\">\"en\"<\/span>&gt;<\/span>\n\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">head<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta<\/span> <span class=\"hljs-attr\">charset<\/span>=<span class=\"hljs-string\">\"utf-8\"<\/span> \/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">link<\/span> <span class=\"hljs-attr\">rel<\/span>=<span class=\"hljs-string\">\"icon\"<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"%PUBLIC_URL%\/favicon.ico\"<\/span> \/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"viewport\"<\/span> <span class=\"hljs-attr\">content<\/span>=<span class=\"hljs-string\">\"width=device-width, initial-scale=1\"<\/span> \/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"theme-color\"<\/span> <span class=\"hljs-attr\">content<\/span>=<span class=\"hljs-string\">\"#000000\"<\/span> \/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"description\"<\/span> <span class=\"hljs-attr\">content<\/span>=<span class=\"hljs-string\">\"React Ecommerce App\"<\/span> \/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">link<\/span> <span class=\"hljs-attr\">rel<\/span>=<span class=\"hljs-string\">\"apple-touch-icon\"<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"%PUBLIC_URL%\/logo192.png\"<\/span> \/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">link<\/span> <span class=\"hljs-attr\">rel<\/span>=<span class=\"hljs-string\">\"manifest\"<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"%PUBLIC_URL%\/manifest.json\"<\/span> \/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">link<\/span> <span class=\"hljs-attr\">rel<\/span>=<span class=\"hljs-string\">\"preconnect\"<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"https:\/\/app.snipcart.com\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">link<\/span> <span class=\"hljs-attr\">rel<\/span>=<span class=\"hljs-string\">\"preconnect\"<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"https:\/\/cdn.snipcart.com\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">link<\/span> <span class=\"hljs-attr\">rel<\/span>=<span class=\"hljs-string\">\"stylesheet\"<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"https:\/\/cdn.snipcart.com\/themes\/v3.2.0\/default\/snipcart.css\"<\/span> \/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"https:\/\/product-gallery.cloudinary.com\/all.js\"<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"text\/javascript\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">title<\/span>&gt;<\/span>Sweeth Tooth<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">title<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">head<\/span>&gt;<\/span>\n\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">body<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">noscript<\/span>&gt;<\/span>You need to enable JavaScript to run this app.<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">noscript<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"root\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span> <span class=\"hljs-attr\">async<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"https:\/\/cdn.snipcart.com\/themes\/v3.2.0\/default\/snipcart.js\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">hidden<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"snipcart\"<\/span> <span class=\"hljs-attr\">data-api-key<\/span>=<span class=\"hljs-string\">\"%REACT_APP_SNIPCART_KEY%\"<\/span> <span class=\"hljs-attr\">data-config-modal-style<\/span>=<span class=\"hljs-string\">\"side\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">body<\/span>&gt;<\/span>\n\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">html<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<h2>How To Fetch and Display the Products<\/h2>\n<p>In this section, you will fetch the data from Airtable using the <code>airtable<\/code> <a href=\"https:\/\/www.npmjs.com\/package\/airtable\">javascript library<\/a> and then display it on the app. To display the product image, you will use the <code>Image<\/code> component from the <code>cloudinary-react<\/code> package.<\/p>\n<p>Modify <code>src\/App.js<\/code> like this.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">import<\/span> React, { useEffect, useState } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { Image, Transformation } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"cloudinary-react\"<\/span>;\n<span class=\"hljs-keyword\">var<\/span> Airtable = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">\"airtable\"<\/span>);\n\n<span class=\"hljs-keyword\">var<\/span> base = <span class=\"hljs-keyword\">new<\/span> Airtable({\n  <span class=\"hljs-attr\">apiKey<\/span>: process.env.REACT_APP_AIRTABLE_API_KEY,\n}).base(process.env.REACT_APP_AIRTABLE_BASE_ID);\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">App<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n  <span class=\"hljs-keyword\">const<\/span> &#91;cakes, setCakes] = useState({});\n\n  useEffect(<span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n    base(<span class=\"hljs-string\">\"cakes\"<\/span>)\n      .select({\n        <span class=\"hljs-attr\">view<\/span>: <span class=\"hljs-string\">\"Grid view\"<\/span>,\n      })\n      .firstPage( <span class=\"hljs-function\">(<span class=\"hljs-params\">err, records<\/span>)=&gt;<\/span> {\n        <span class=\"hljs-keyword\">if<\/span> (err) {\n          <span class=\"hljs-built_in\">console<\/span>.error(err);\n          <span class=\"hljs-keyword\">return<\/span>;\n        }\n        setCakes(records);\n      });\n  }, &#91;]);\n\n  <span class=\"hljs-keyword\">return<\/span> (\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"bg-pink-100 min-h-screen\"<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"container px-3  mx-auto\"<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\" text-5xl md:text-7xl text-red-800 px-4 pt-2 leading-normal mb-2\"<\/span>&gt;<\/span>\n          Sweet Tooth\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\n        {cakes &amp;&amp; console.log(cakes)}\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n  );\n}\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> App;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>You start by importing <code>useState()<\/code> and <code>useEffect()<\/code> hooks. You also import <code>Image<\/code> and <code>Transformation<\/code> components from <code>cloudinary-react<\/code>; these components display the product\u2019s image on the app.<\/p>\n<p>You create an instance of <code>airtable<\/code> and pass your Airtable API Key and base\u2019s id to it. Using the <code>useState()<\/code> hook, you create a state named <code>cakes<\/code> with an initial value of an empty array. This state will store the data fetched from Airtable.<\/p>\n<p>To fetch the data, you use the <code>select<\/code> method to retrieve the data in <code>cakes<\/code>. The <code>select<\/code> returns a query object. To fetch the records matching that query, you use the <code>firstPage<\/code> method of the query object. If a successful response is returned from the <code>firstPage<\/code> method, you store the fetched records in the <code>cakes<\/code> state using the <code>setCakes()<\/code> method.<\/p>\n<p>You create a simple layout for your ecommerce app using Tailwind CSS and logs the <code>cakes<\/code> state in the console using the JavaScript expression <code>{cakes &amp;&amp; console.log(cakes)}<\/code>.<\/p>\n<p>Start your development server and navigate to <a href=\"http:\/\/localhost:3000\/\">http:\/\/localhost:3000\/<\/a> in your browser. Here is how your app will look like.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/jesse-thisdot\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/v1622101831\/e-603fc45fe6c0b4006873802f\/lf0byice4zbcjvglrgql.png\" alt=\"Data in Console\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1909\" height=\"861\"\/><\/p>\n<p>Here is how the product data stored in the <code>cakes<\/code> array looks like.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JSON \/ JSON with Comments\" data-shcb-language-slug=\"json\"><span><code class=\"hljs language-json shcb-wrap-lines\">{\n  <span class=\"hljs-attr\">\"_table\"<\/span>: {\n    <span class=\"hljs-attr\">\"_base\"<\/span>: {\n      <span class=\"hljs-attr\">\"_airtable\"<\/span>: {},\n      <span class=\"hljs-attr\">\"_id\"<\/span>: <span class=\"hljs-string\">\"app2dz674vyBaqHT8\"<\/span>\n    },\n    <span class=\"hljs-attr\">\"id\"<\/span>: <span class=\"hljs-literal\">null<\/span>,\n    <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"cakes\"<\/span>\n  },\n  <span class=\"hljs-attr\">\"id\"<\/span>: <span class=\"hljs-string\">\"recxVHtospJjb0tYP\"<\/span>,\n  <span class=\"hljs-attr\">\"_rawJson\"<\/span>: {\n    <span class=\"hljs-attr\">\"id\"<\/span>: <span class=\"hljs-string\">\"recxVHtospJjb0tYP\"<\/span>,\n    <span class=\"hljs-attr\">\"fields\"<\/span>: {\n      <span class=\"hljs-attr\">\"price\"<\/span>: <span class=\"hljs-number\">30<\/span>,\n      <span class=\"hljs-attr\">\"description\"<\/span>: <span class=\"hljs-string\">\"A butter cake is a cake in which one of the main ingredients is butter. \\n\"<\/span>,\n      <span class=\"hljs-attr\">\"id\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n      <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Butter Cake\"<\/span>,\n      <span class=\"hljs-attr\">\"public_id\"<\/span>: <span class=\"hljs-string\">\"sweet-tooth\/bl7idqn4103cdpmctau7\"<\/span>\n    },\n    <span class=\"hljs-attr\">\"createdTime\"<\/span>: <span class=\"hljs-string\">\"2021-05-23T09:50:03.000Z\"<\/span>\n  },\n  <span class=\"hljs-attr\">\"fields\"<\/span>: {\n    <span class=\"hljs-attr\">\"price\"<\/span>: <span class=\"hljs-number\">30<\/span>,\n    <span class=\"hljs-attr\">\"description\"<\/span>: <span class=\"hljs-string\">\"A butter cake is a cake in which one of the main ingredients is butter. \\n\"<\/span>,\n    <span class=\"hljs-attr\">\"id\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n    <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Butter Cake\"<\/span>,\n    <span class=\"hljs-attr\">\"public_id\"<\/span>: <span class=\"hljs-string\">\"sweet-tooth\/bl7idqn4103cdpmctau7\"<\/span>\n  }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JSON \/ JSON with Comments<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">json<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Now that you have the product\u2019s data, the next step is to iterate over the data array or <code>cakes<\/code> array and display them on the app. For this, you will create a Product card and reuse it with different product\u2019s data.<\/p>\n<p>Remove the JavaScript expression <code>{cakes &amp;&amp; console.log(cakes)}<\/code>. Add the following code under the title, <strong>Sweet Tooth<\/strong> or the <code>&lt;h1&gt;<\/code> tag.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"container flex flex-wrap -mx-2 px-4 overflow-hidden\"<\/span>&gt;<\/span>\n  {cakes.length &gt; 0 &amp;&amp;\n    cakes.map((cake) =&gt; (\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>\n        <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"my-2 px-2 w-full overflow-hidden sm:w-full md:w-1\/2 lg:w-1\/3 xl:w-1\/3 rounded-xl shadow-4xl\"<\/span>\n        <span class=\"hljs-attr\">key<\/span>=<span class=\"hljs-string\">{cake.fields.id}<\/span>\n      &gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Image<\/span>\n          <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"rounded-t-xl\"<\/span>\n          <span class=\"hljs-attr\">cloudName<\/span>=<span class=\"hljs-string\">{process.env.REACT_APP_CLOUDINARY_CLOUD_NAME}<\/span>\n          <span class=\"hljs-attr\">publicId<\/span>=<span class=\"hljs-string\">{cake.fields.public_id}<\/span>\n          <span class=\"hljs-attr\">format<\/span>=<span class=\"hljs-string\">\"webp\"<\/span>\n          <span class=\"hljs-attr\">secure<\/span>=<span class=\"hljs-string\">\"true\"<\/span>\n        &gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Transformation<\/span> <span class=\"hljs-attr\">quality<\/span>=<span class=\"hljs-string\">\"60\"<\/span> \/&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Image<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"-mt-1 rounded-b-xl bg-white px-4 py-3\"<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"px-1\"<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"text-4xl text-gray-600 font-medium underline hover:text-pink-600\"<\/span>&gt;<\/span>\n              {cake.fields.name}\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"text-md py-4 leading-6 overflow-ellipsis text-gray-600\"<\/span>&gt;<\/span>\n              {cake.fields.description}\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"px-6 py-3\"<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"text-3xl inline-block  px-2 text-gray-800\"<\/span>&gt;<\/span>\n              {cake.fields.price}$\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span>\n              <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"snipcart-add-item text-white float-right flex flex-auto justify-center items-center uppercase text-md px-2 bg-green-400 hover:bg-green-500  w-36  h-12 border-transparent font-medium rounded-3xl\"<\/span>\n              <span class=\"hljs-attr\">data-item-id<\/span>=<span class=\"hljs-string\">{cake.fields.id}<\/span>\n              <span class=\"hljs-attr\">data-item-price<\/span>=<span class=\"hljs-string\">{cake.fields.price}<\/span>\n              <span class=\"hljs-attr\">data-item-url<\/span>=<span class=\"hljs-string\">\"\/\"<\/span>\n              <span class=\"hljs-attr\">data-item-description<\/span>=<span class=\"hljs-string\">{cake.fields.description}<\/span>\n              <span class=\"hljs-attr\">data-item-image<\/span>=<span class=\"hljs-string\">{<\/span>`<span class=\"hljs-attr\">https:<\/span>\/\/<span class=\"hljs-attr\">res.cloudinary.com<\/span>\/${<span class=\"hljs-attr\">process.env.REACT_APP_CLOUDINARY_CLOUD_NAME<\/span>}\/<span class=\"hljs-attr\">image<\/span>\/<span class=\"hljs-attr\">upload<\/span>\/<span class=\"hljs-attr\">q_10<\/span>\/${<span class=\"hljs-attr\">cake.fields.public_id<\/span>}`}\n              <span class=\"hljs-attr\">data-item-name<\/span>=<span class=\"hljs-string\">{cake.fields.name}<\/span>\n            &gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">svg<\/span>\n                <span class=\"hljs-attr\">xmlns<\/span>=<span class=\"hljs-string\">\"http:\/\/www.w3.org\/2000\/svg\"<\/span>\n                <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"h-7 w-7 mr-1\"<\/span>\n                <span class=\"hljs-attr\">fill<\/span>=<span class=\"hljs-string\">\"none\"<\/span>\n                <span class=\"hljs-attr\">viewBox<\/span>=<span class=\"hljs-string\">\"0 0 24 24\"<\/span>\n                <span class=\"hljs-attr\">stroke<\/span>=<span class=\"hljs-string\">\"currentColor\"<\/span>\n              &gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">path<\/span>\n                  <span class=\"hljs-attr\">strokeLinecap<\/span>=<span class=\"hljs-string\">\"round\"<\/span>\n                  <span class=\"hljs-attr\">strokeLinejoin<\/span>=<span class=\"hljs-string\">\"round\"<\/span>\n                  <span class=\"hljs-attr\">strokeWidth<\/span>=<span class=\"hljs-string\">{2}<\/span>\n                  <span class=\"hljs-attr\">d<\/span>=<span class=\"hljs-string\">\"M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z\"<\/span>\n                \/&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">svg<\/span>&gt;<\/span>\n              buy now\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    ))}\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>You start by creating a responsive flex div with Tailwind CSS and then map over the <code>cakes<\/code> array inside it. You display the product\u2019s image using the <code>Image<\/code> component and reduce its quality using the <code>Transformation<\/code> component. You pass the <code>public_id<\/code> of the product\u2019s image stored in Cloudinary and your Cloudinary cloud name to the <code>Image<\/code> component.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Image<\/span>\n  <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"rounded-t-xl\"<\/span>\n  <span class=\"hljs-attr\">cloudName<\/span>=<span class=\"hljs-string\">{process.env.REACT_APP_CLOUDINARY_CLOUD_NAME}<\/span>\n  <span class=\"hljs-attr\">publicId<\/span>=<span class=\"hljs-string\">{cake.fields.public_id}<\/span>\n  <span class=\"hljs-attr\">format<\/span>=<span class=\"hljs-string\">\"webp\"<\/span>\n  <span class=\"hljs-attr\">secure<\/span>=<span class=\"hljs-string\">\"true\"<\/span>\n&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Transformation<\/span> <span class=\"hljs-attr\">quality<\/span>=<span class=\"hljs-string\">\"60\"<\/span> \/&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Image<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>You display the product\u2019s name inside a button; in the next section, you will use it to open a modal containing the respective product\u2019s gallery. You also display the product\u2019s description and price in the product\u2019s card.<\/p>\n<p>Here is how your ecommerce app will look like.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/jesse-thisdot\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/v1622101862\/e-603fc45fe6c0b4006873802f\/zhzrvy2v3hprt1jtih2k.png\" alt=\"Sweet Tooth\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1920\" height=\"908\"\/><\/p>\n<p>In the <code>buy now<\/code> button, you pass the product\u2019s data required by Snipcart. You also pass your product\u2019s image URL generated with your Cloudinary cloud name and the <code>public_id<\/code> of the image. to Snipcart.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span>\n  <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"snipcart-add-item text-white float-right flex flex-auto justify-center items-center uppercase text-md px-2 bg-green-400 hover:bg-green-500  w-36  h-12 border-transparent font-medium rounded-3xl\"<\/span>\n  <span class=\"hljs-attr\">data-item-id<\/span>=<span class=\"hljs-string\">{cake.fields.id}<\/span>\n  <span class=\"hljs-attr\">data-item-price<\/span>=<span class=\"hljs-string\">{cake.fields.price}<\/span>\n  <span class=\"hljs-attr\">data-item-url<\/span>=<span class=\"hljs-string\">\"\/\"<\/span>\n  <span class=\"hljs-attr\">data-item-description<\/span>=<span class=\"hljs-string\">{cake.fields.description}<\/span>\n  <span class=\"hljs-attr\">data-item-image<\/span>=<span class=\"hljs-string\">{<\/span>`<span class=\"hljs-attr\">https:<\/span>\/\/<span class=\"hljs-attr\">res.cloudinary.com<\/span>\/${<span class=\"hljs-attr\">process.env.REACT_APP_CLOUDINARY_CLOUD_NAME<\/span>}\/<span class=\"hljs-attr\">image<\/span>\/<span class=\"hljs-attr\">upload<\/span>\/<span class=\"hljs-attr\">q_10<\/span>\/${<span class=\"hljs-attr\">cake.fields.public_id<\/span>}`}\n  <span class=\"hljs-attr\">data-item-name<\/span>=<span class=\"hljs-string\">{cake.fields.name}<\/span>\n&gt;<\/span>\n  buy now\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>When the user clicks the <code>buy now<\/code> button, the Snipcart cart comes into action. Users can use this cart to modify products in their cart and proceed to checkout.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/jesse-thisdot\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/v1622101917\/e-603fc45fe6c0b4006873802f\/fmqmpr7qdbnkdthcpqsa.gif\" alt=\"Sweet Tooth GIF\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"600\" height=\"285\"\/><\/p>\n<h2>How To Add Cloudinary Product Gallery<\/h2>\n<p>In this section, you will integrate Cloudinary\u2019s product gallery with your ecommerce app. Before using the product gallery, make sure the <strong>Settings \u2192 Restricted media types \u2192 Resource list<\/strong> is not selected in your account settings.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/jesse-thisdot\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/v1622101989\/e-603fc45fe6c0b4006873802f\/nly9mwak5vs1jqh8jpfe.png\" alt=\"Cloudinary Settings\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1360\" height=\"868\"\/><\/p>\n<p>Your product gallery will need different images of the product, i.e., <strong>cakes<\/strong>. You will need to upload few pictures related to the product in your Cloudianry\u2019s account <code>sweet-tooth<\/code> folder. One way is to use the <strong>Upload Widget<\/strong>, search for the images online, and then upload them. You will also need to tag all the pictures with their respective product\u2019s name, as shown below.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/jesse-thisdot\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/v1622102041\/e-603fc45fe6c0b4006873802f\/i0emi6denkxhmybovdx8.png\" alt=\"Upload Images with Tag\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1129\" height=\"899\"\/><\/p>\n<p>In the <code>App.js<\/code> file, you will create two functions, <code>openGallery()<\/code>, which opens the product gallery, and <code>closeGallery<\/code>, which closes the product gallery. Since the product gallery will render inside a modal, you will need to define a state named <code>showModal<\/code> to show or hide the modal. You will also need to define another state, <code>currentProduct<\/code>, to track which product the user has selected.<\/p>\n<p>The <code>currentProduct<\/code> state has an initial value of <code>Butter Cake<\/code> since you cant render the product gallery with empty strings, or your app will crash.<\/p>\n<p>Add the following code after the initialization of <code>cakes<\/code> state in the <code>App.js<\/code> file.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">const<\/span> &#91;showModal, setShowModal] = useState(<span class=\"hljs-literal\">false<\/span>);\n<span class=\"hljs-keyword\">const<\/span> &#91;currentProduct, setCurrentProduct] = useState(<span class=\"hljs-string\">\"Butter Cake\"<\/span>);\n\n<span class=\"hljs-keyword\">const<\/span> myWidget = <span class=\"hljs-built_in\">window<\/span>.cloudinary.galleryWidget({\n  <span class=\"hljs-attr\">cloudName<\/span>: process.env.REACT_APP_CLOUDINARY_CLOUD_NAME,\n  <span class=\"hljs-attr\">mediaAssets<\/span>: &#91;{ <span class=\"hljs-attr\">tag<\/span>: currentProduct }],\n  <span class=\"hljs-attr\">secure<\/span>: <span class=\"hljs-literal\">true<\/span>,\n  <span class=\"hljs-attr\">aspectRatio<\/span>: <span class=\"hljs-string\">\"16:9\"<\/span>,\n  <span class=\"hljs-attr\">container<\/span>: <span class=\"hljs-string\">\"#my-gallery\"<\/span>,\n});\nmyWidget.render();\n\n<span class=\"hljs-keyword\">const<\/span> openGallery = <span class=\"hljs-function\">(<span class=\"hljs-params\">selectedProduct<\/span>) =&gt;<\/span> {\n  setCurrentProduct(selectedProduct);\n  myWidget.update({ <span class=\"hljs-attr\">mediaAssets<\/span>: &#91;{ <span class=\"hljs-attr\">tag<\/span>: currentProduct }] });\n  setShowModal(<span class=\"hljs-literal\">true<\/span>);\n};\n\n<span class=\"hljs-keyword\">const<\/span> closeGalllery = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n  myWidget.destroy();\n  setShowModal(<span class=\"hljs-literal\">false<\/span>);\n};\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>You use the <code>cloudinary.galleryWidget()<\/code> method to initialize your product gallery with the following configuration.<\/p>\n<ul>\n<li>\n<code>cloudName<\/code> &#8211; Name of your Cloudinary cloud.<\/li>\n<li>\n<code>mediaAssets<\/code> &#8211; An array of assets. The individual assets in the array can be described either by an Asset object with <code>tag<\/code> of the images or by a PublicID string.<\/li>\n<li>\n<code>container<\/code> &#8211; The containing element on the page for the Product Gallery widget. Here it is a div with <code>id=&quot;my-gallery&quot;<\/code> inside the modal.<\/li>\n<li>\n<code>aspectRatio<\/code> &#8211; The aspect ratio of the main viewer.<\/li>\n<\/ul>\n<p>Since the modal will appear only when the button or product\u2019s name is clicked, you will not see the gallery although it has been rendered.<\/p>\n<p>In the <code>openGallery()<\/code> function, you set the state of the <code>currentProduct<\/code> to <code>selectedProduct<\/code>, i.e., the product\u2019s name passed when the user clicks the respective product. You then update the gallery with the current product using the gallery\u2019s <code>.update()<\/code> method. Finally, the <code>showModal<\/code> state is set to true to display the modal and the gallery.<\/p>\n<p>In the <code>closeGallery()<\/code> function, you destroy the product gallery with the <code>.destroy()<\/code> method and then close the modal by setting the <code>showModal<\/code> state to false. You can read more about Cloudinary product\u2019s gallery methods <a href=\"https:\/\/cloudinary.com\/documentation\/product_gallery_reference#destroy\">here<\/a>.<\/p>\n<p>The next step is to add the <code>openGallery()<\/code> function to the <code>onClick<\/code> event of the <code>buy now<\/code> button. Update the <code>buy now<\/code> button like this.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span>\n  <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"text-4xl text-gray-600 font-medium font-product-title underline hover:text-pink-600\"<\/span>\n  <span class=\"hljs-attr\">onClick<\/span>=<span class=\"hljs-string\">{()<\/span> =&gt;<\/span> openGallery(cake.fields.name)}\n&gt;\n  {cake.fields.name}\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>The last step is to create the modal where the gallery will be shown. Add the following code before the third closing div at the bottom.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">{\n  showModal ? (\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"justify-center items-center flex overflow-x-hidden overflow-y-auto fixed inset-0 z-50 outline-none focus:outline-none\"<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"absolute w-4\/6 my-8 mx-auto\"<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"border-0 rounded-lg shadow-lg relative flex flex-col w-full bg-white outline-none focus:outline-none\"<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"flex items-start justify-between p-4 border-b border-solid border-blueGray-200 rounded-t\"<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h3<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"text-3xl text-pink-800 font-medium\"<\/span>&gt;<\/span>\n                {currentProduct} Gallery\n              <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h3<\/span>&gt;<\/span>\n\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span>\n                <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"p-1 bg-transparent ml-auto border-0 text-red-600 float-right text-3xl leading-none font-semibold outline-none focus:outline-none\"<\/span>\n                <span class=\"hljs-attr\">onClick<\/span>=<span class=\"hljs-string\">{()<\/span> =&gt;<\/span> {\n                  closeGalllery();\n                }}\n              &gt;\n                X\n              <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"p-4\"<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"my-gallery\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"flex items-center justify-end p-4 border-t border-solid border-blueGray-200 rounded-b\"<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span>\n                <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"text-red-500 background-transparent font-bold uppercase px-6 py-2 text-md outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150\"<\/span>\n                <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"button\"<\/span>\n                <span class=\"hljs-attr\">onClick<\/span>=<span class=\"hljs-string\">{()<\/span> =&gt;<\/span> {\n                  closeGalllery();\n                }}\n              &gt;\n                Close\n              <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"opacity-25 fixed inset-0 z-40 bg-black\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/&gt;<\/span><\/span>\n  ) : <span class=\"hljs-literal\">null<\/span>\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>In the above code, the modal appears according to the state <code>showModal<\/code>. Inside the modal, you have created the div with <code>id=&quot;my-gallery&quot;<\/code>, where the product gallery is rendered. You have also created two buttons to close the modal, namely <code>X<\/code> and <code>CLOSE<\/code>; when these buttons are clicked, the <code>closeGallery()<\/code> function is executed, hiding the modal and destroying the product gallery to avoid memory leakage and performance issues.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/jesse-thisdot\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/v1622102082\/e-603fc45fe6c0b4006873802f\/xfxdy2vkfax4u9qxatsw.gif\" alt=\"Product Galllery GIF\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"600\" height=\"281\"\/><\/p>\n<h2>Conclusion<\/h2>\n<p>In this media jam, we discussed how to build an ecommerce app in React using Airtable, Cloudinary, and Snipcart. We also saw how to integrate Cloudinary\u2019s product gallery with a react application.<\/p>\n<p>In this tutorial, we used Tailwind CSS to style our app; you can use any React UI library like <a href=\"https:\/\/chakra-ui.com\/\">Chakra UI<\/a>, <a href=\"https:\/\/material-ui.com\/\">Material UI<\/a>, <a href=\"https:\/\/react-bootstrap.github.io\/\">React Bootstrap<\/a>, etc.<\/p>\n<p>Here are some additional resources that can be helpful:<\/p>\n<ul>\n<li>\n<a href=\"https:\/\/airtable.com\/api\/meta\">Airtable API Docs<\/a>\n<\/li>\n<li>\n<a href=\"https:\/\/docs.snipcart.com\/v3\/\">Snipcart Docs<\/a>\n<\/li>\n<li>\n<a href=\"https:\/\/cloudinary.com\/documentation\/product_gallery\">Cloudinary Product Gallery Documentation<\/a>\n<\/li>\n<\/ul>\n<p>Happy coding!<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":41,"featured_media":28023,"comment_status":"","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[134,246,371],"class_list":["post-28022","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-guest-post","tag-react","tag-under-review"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.6 (Yoast SEO v26.9) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>How To Build an Ecommerce App With React<\/title>\n<meta name=\"description\" content=\"In this media jam, we will discuss how to build an ecommerce app in React using Airtable, Cloudinary, and Snipcart. We will use Airtable to store product data and use Cloudinary&#039;s Product Gallery to showcase different product images. In this tutorial, we will build an ecommerce site for a cake shop named Sweet Tooth and use various cakes as products.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How To Build an Ecommerce App With React\" \/>\n<meta property=\"og:description\" content=\"In this media jam, we will discuss how to build an ecommerce app in React using Airtable, Cloudinary, and Snipcart. We will use Airtable to store product data and use Cloudinary&#039;s Product Gallery to showcase different product images. In this tutorial, we will build an ecommerce site for a cake shop named Sweet Tooth and use various cakes as products.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2021-06-02T08:57:57+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925654\/Web_Assets\/blog\/219a9df1891ab65d73ab5328c729df6d57fe96d1-1898x908-1_28023ea75c\/219a9df1891ab65d73ab5328c729df6d57fe96d1-1898x908-1_28023ea75c.png?_i=AA\" \/>\n\t<meta property=\"og:image:width\" content=\"1898\" \/>\n\t<meta property=\"og:image:height\" content=\"908\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"NewsArticle\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"How To Build an Ecommerce App With React\",\"datePublished\":\"2021-06-02T08:57:57+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/\"},\"wordCount\":8,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925654\/Web_Assets\/blog\/219a9df1891ab65d73ab5328c729df6d57fe96d1-1898x908-1_28023ea75c\/219a9df1891ab65d73ab5328c729df6d57fe96d1-1898x908-1_28023ea75c.png?_i=AA\",\"keywords\":[\"Guest Post\",\"React\",\"Under Review\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2021\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/\",\"url\":\"https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/\",\"name\":\"How To Build an Ecommerce App With React\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925654\/Web_Assets\/blog\/219a9df1891ab65d73ab5328c729df6d57fe96d1-1898x908-1_28023ea75c\/219a9df1891ab65d73ab5328c729df6d57fe96d1-1898x908-1_28023ea75c.png?_i=AA\",\"datePublished\":\"2021-06-02T08:57:57+00:00\",\"description\":\"In this media jam, we will discuss how to build an ecommerce app in React using Airtable, Cloudinary, and Snipcart. We will use Airtable to store product data and use Cloudinary's Product Gallery to showcase different product images. In this tutorial, we will build an ecommerce site for a cake shop named Sweet Tooth and use various cakes as products.\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925654\/Web_Assets\/blog\/219a9df1891ab65d73ab5328c729df6d57fe96d1-1898x908-1_28023ea75c\/219a9df1891ab65d73ab5328c729df6d57fe96d1-1898x908-1_28023ea75c.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925654\/Web_Assets\/blog\/219a9df1891ab65d73ab5328c729df6d57fe96d1-1898x908-1_28023ea75c\/219a9df1891ab65d73ab5328c729df6d57fe96d1-1898x908-1_28023ea75c.png?_i=AA\",\"width\":1898,\"height\":908},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"How To Build an Ecommerce App With React\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"name\":\"Cloudinary Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cloudinary.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\",\"name\":\"Cloudinary Blog\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"width\":312,\"height\":60,\"caption\":\"Cloudinary Blog\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"How To Build an Ecommerce App With React","description":"In this media jam, we will discuss how to build an ecommerce app in React using Airtable, Cloudinary, and Snipcart. We will use Airtable to store product data and use Cloudinary's Product Gallery to showcase different product images. In this tutorial, we will build an ecommerce site for a cake shop named Sweet Tooth and use various cakes as products.","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:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/","og_locale":"en_US","og_type":"article","og_title":"How To Build an Ecommerce App With React","og_description":"In this media jam, we will discuss how to build an ecommerce app in React using Airtable, Cloudinary, and Snipcart. We will use Airtable to store product data and use Cloudinary's Product Gallery to showcase different product images. In this tutorial, we will build an ecommerce site for a cake shop named Sweet Tooth and use various cakes as products.","og_url":"https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/","og_site_name":"Cloudinary Blog","article_published_time":"2021-06-02T08:57:57+00:00","og_image":[{"width":1898,"height":908,"url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925654\/Web_Assets\/blog\/219a9df1891ab65d73ab5328c729df6d57fe96d1-1898x908-1_28023ea75c\/219a9df1891ab65d73ab5328c729df6d57fe96d1-1898x908-1_28023ea75c.png?_i=AA","type":"image\/png"}],"twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/"},"author":{"name":"","@id":""},"headline":"How To Build an Ecommerce App With React","datePublished":"2021-06-02T08:57:57+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/"},"wordCount":8,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925654\/Web_Assets\/blog\/219a9df1891ab65d73ab5328c729df6d57fe96d1-1898x908-1_28023ea75c\/219a9df1891ab65d73ab5328c729df6d57fe96d1-1898x908-1_28023ea75c.png?_i=AA","keywords":["Guest Post","React","Under Review"],"inLanguage":"en-US","copyrightYear":"2021","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/","url":"https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/","name":"How To Build an Ecommerce App With React","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925654\/Web_Assets\/blog\/219a9df1891ab65d73ab5328c729df6d57fe96d1-1898x908-1_28023ea75c\/219a9df1891ab65d73ab5328c729df6d57fe96d1-1898x908-1_28023ea75c.png?_i=AA","datePublished":"2021-06-02T08:57:57+00:00","description":"In this media jam, we will discuss how to build an ecommerce app in React using Airtable, Cloudinary, and Snipcart. We will use Airtable to store product data and use Cloudinary's Product Gallery to showcase different product images. In this tutorial, we will build an ecommerce site for a cake shop named Sweet Tooth and use various cakes as products.","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925654\/Web_Assets\/blog\/219a9df1891ab65d73ab5328c729df6d57fe96d1-1898x908-1_28023ea75c\/219a9df1891ab65d73ab5328c729df6d57fe96d1-1898x908-1_28023ea75c.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925654\/Web_Assets\/blog\/219a9df1891ab65d73ab5328c729df6d57fe96d1-1898x908-1_28023ea75c\/219a9df1891ab65d73ab5328c729df6d57fe96d1-1898x908-1_28023ea75c.png?_i=AA","width":1898,"height":908},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/how-to-build-an-ecommerce-app-with-react\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"How To Build an Ecommerce App With React"}]},{"@type":"WebSite","@id":"https:\/\/cloudinary.com\/blog\/#website","url":"https:\/\/cloudinary.com\/blog\/","name":"Cloudinary Blog","description":"","publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cloudinary.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/cloudinary.com\/blog\/#organization","name":"Cloudinary Blog","url":"https:\/\/cloudinary.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","width":312,"height":60,"caption":"Cloudinary Blog"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":""}]}},"jetpack_featured_media_url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925654\/Web_Assets\/blog\/219a9df1891ab65d73ab5328c729df6d57fe96d1-1898x908-1_28023ea75c\/219a9df1891ab65d73ab5328c729df6d57fe96d1-1898x908-1_28023ea75c.png?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28022","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/comments?post=28022"}],"version-history":[{"count":0,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28022\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/28023"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=28022"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=28022"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=28022"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}