{"id":1814,"date":"2021-09-27T12:14:30","date_gmt":"2021-09-27T12:14:30","guid":{"rendered":"https:\/\/www.reloadly.com\/blog\/?p=1814"},"modified":"2021-10-05T11:33:16","modified_gmt":"2021-10-05T11:33:16","slug":"building-a-promotion-tracker-with-react-and-reloadlys-api","status":"publish","type":"post","link":"https:\/\/blog.reloadly.com\/blog\/building-a-promotion-tracker-with-react-and-reloadlys-api\/","title":{"rendered":"Building a Promotion Tracker with React and Reloadly&#8217;s API"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_46 ez-toc-wrap-left counter-hierarchy ez-toc-counter ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\">Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"ez-toc-toggle-icon-1\"><label for=\"item-69d2cebd80f8b\" aria-label=\"Table of Content\"><span style=\"display: flex;align-items: center;width: 35px;height: 30px;justify-content: center;direction:ltr;\"><svg style=\"fill: #000000;color:#000000\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #000000;color:#000000\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/label><input  type=\"checkbox\" id=\"item-69d2cebd80f8b\"><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 eztoc-visibility-hide-by-default' ><ul class='ez-toc-list-level-3'><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/blog.reloadly.com\/blog\/building-a-promotion-tracker-with-react-and-reloadlys-api\/#Tools_you_will_need\" title=\"Tools you will need\">Tools you will need<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/blog.reloadly.com\/blog\/building-a-promotion-tracker-with-react-and-reloadlys-api\/#Creating_a_React_application\" title=\"Creating a React application\">Creating a React application<\/a><ul class='ez-toc-list-level-3'><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/blog.reloadly.com\/blog\/building-a-promotion-tracker-with-react-and-reloadlys-api\/#Getting_your_Reloadly_access_token\" title=\"Getting your Reloadly access token\">Getting your Reloadly access token<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/blog.reloadly.com\/blog\/building-a-promotion-tracker-with-react-and-reloadlys-api\/#Safeguarding_your_access_token\" title=\"Safeguarding your access token\">Safeguarding your access token<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/blog.reloadly.com\/blog\/building-a-promotion-tracker-with-react-and-reloadlys-api\/#Fetching_data_with_hooks_and_Axios\" title=\"Fetching data with hooks and Axios\">Fetching data with hooks and Axios<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/blog.reloadly.com\/blog\/building-a-promotion-tracker-with-react-and-reloadlys-api\/#Viewing_an_operators_promotion_data\" title=\"Viewing an operator\u2019s promotion data\">Viewing an operator\u2019s promotion data<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/blog.reloadly.com\/blog\/building-a-promotion-tracker-with-react-and-reloadlys-api\/#Summary\" title=\"Summary\">Summary<\/a><\/li><\/ul><\/nav><\/div>\n\n<p>Airtime can largely be seen as a necessity in today\u2019s world thus when making top-ups, customers are always in search of value. It would be great if an application existed where a user could check for available airtime or data bonuses and promotions in any region around the world. <\/p>\n\n\n\n<p>In this article, we\u2019ll build an application that meets this need using React &#8211; a JavaScript framework, and\u00a0<a href=\"https:\/\/reloadly.com\/\">Reloadly<\/a>\u00a0&#8211; a service for global airtime top-ups.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Tools_you_will_need\"><\/span>Tools you will need<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<ul><li><a href=\"https:\/\/nodejs.org\/en\/\">Node<\/a>&nbsp;: A back-end JavaScript runtime environment that executes JavaScript code outside a web browser.<\/li><li><a href=\"https:\/\/docs.npmjs.com\/downloading-and-installing-node-js-and-npm\">npm<\/a>&nbsp;: A package manager for Node.<\/li><li><a href=\"https:\/\/www.npmjs.com\/package\/dotenv\">dotenv<\/a>&nbsp;: A module that loads environment variables from an&nbsp;<code>.env<\/code>&nbsp;file<\/li><li><a href=\"https:\/\/www.npmjs.com\/package\/axios\">axios<\/a>: A promise based HTTP client for the browser and NodeJS<\/li><li><a href=\"https:\/\/www.npmjs.com\/package\/react-bootstrap\">react-bootstrap<\/a>: A library that renders Bootstrap components in React applications<\/li><\/ul>\n\n\n\n<p>Also, intermediate knowledge of JavaScript and React would be fundamental to digesting this tutorial.<\/p>\n\n\n\n<p>If you want to check out the source code of this application before reading the article, you can find it&nbsp;<a href=\"https:\/\/github.com\/fullstackmafia\/reloadly-react-promotion-tracker\">here<\/a>.<\/p>\n\n\n\n<div style=\"height:20px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Creating_a_React_application\"><\/span>Creating a React application<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>The first step to getting started is creating a skeletal React application. The fastest way to do this is to use the&nbsp;<code>create-react-app<\/code>&nbsp;command via your terminal:<\/p>\n\n\n\n<div style=\"height:31px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<pre class=\"wp-block-code\"><code> # Create a new React application with the below command\n\n    npx create-react-app reloadly-app\n\n    # Navigate to the newly created React application\n\n    cd reloadly-app\n\n    # Launch the application on your browser\n\n    npm start<\/code><\/pre>\n\n\n\n<div style=\"height:29px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Note that&nbsp;<code>npx<\/code>&nbsp;on the first line is not a typo, it\u2019s a package runner tool that comes with&nbsp;<code>npm<\/code>. Your new application\u2019s folder should look somewhat like this when you are done creating it:<\/p>\n\n\n\n<div style=\"height:31px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<pre class=\"wp-block-code\"><code>RELOADLY-APP\n\npublic\n    index.html\n    manifest.json\nsrc\n    App.css\n    App.js\n    App.test.js\n    index.css\n    index.js\n    logo.svg\n    reportWebVitals.js\n    setupTests.js\n.gitignore\n package-lock.json\n package.json\n README.md<\/code><\/pre>\n\n\n\n<div style=\"height:29px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>When the app is launched, you should see a web page similar to the image below. At this point, all you\u2019ll see is React\u2019s default web page<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"880\" height=\"468\" src=\"https:\/\/www.reloadly.com\/blog\/wp-content\/uploads\/2021\/09\/react.png\" alt=\"\" class=\"wp-image-1815\" srcset=\"https:\/\/blog.reloadly.com\/blog\/wp-content\/uploads\/2021\/09\/react.png 880w, https:\/\/blog.reloadly.com\/blog\/wp-content\/uploads\/2021\/09\/react-300x160.png 300w, https:\/\/blog.reloadly.com\/blog\/wp-content\/uploads\/2021\/09\/react-768x408.png 768w\" sizes=\"(max-width: 880px) 100vw, 880px\" \/><\/figure>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Getting_your_Reloadly_access_token\"><\/span>Getting your Reloadly access token<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>To access airtime bonus information from Reloadly, you\u2019ll need an access token. This can be gotten by signing up for an account on Reloadly and using your client credentials to make a POST request for an access token. On your Reloadly dashboard, you can view your client credentials in the Developers section as depicted below:<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"354\" src=\"https:\/\/www.reloadly.com\/blog\/wp-content\/uploads\/2021\/09\/image-7-1-1024x354.png\" alt=\"\" class=\"wp-image-1818\" srcset=\"https:\/\/blog.reloadly.com\/blog\/wp-content\/uploads\/2021\/09\/image-7-1-1024x354.png 1024w, https:\/\/blog.reloadly.com\/blog\/wp-content\/uploads\/2021\/09\/image-7-1-300x104.png 300w, https:\/\/blog.reloadly.com\/blog\/wp-content\/uploads\/2021\/09\/image-7-1-768x265.png 768w, https:\/\/blog.reloadly.com\/blog\/wp-content\/uploads\/2021\/09\/image-7-1-1536x531.png 1536w, https:\/\/blog.reloadly.com\/blog\/wp-content\/uploads\/2021\/09\/image-7-1.png 1667w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div style=\"height:31px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>It&#8217;s important to note here that your client credentials should be kept private and secure at all times. Use these credentials to make a&nbsp;<code>POST<\/code>&nbsp;request to the&nbsp;<code>https:\/\/auth.reloadly.com\/oauth\/token<\/code>&nbsp;URL with the following body parameters:<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<pre class=\"wp-block-code\"><code>  {\n      \"client_id\":\"YOUR_CLIENT_ID\",\n      \"client_secret\":\"YOUR_CLIENT_SECRET\",\n      \"grant_type\":\"client_credentials\",\n      \"audience\":\"https:\/\/topups.reloadly.com\"\n    }<\/code><\/pre>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<figure class=\"wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"api-request-for-access-token\" width=\"500\" height=\"375\" src=\"https:\/\/www.youtube.com\/embed\/45toCu-QTFE?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<div style=\"height:32px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Safeguarding_your_access_token\"><\/span>Safeguarding your access token<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>On getting your access token, you\u2019ll need a place to safely store it. This can be done using a&nbsp;<code>.env<\/code>&nbsp;file. First navigate to your terminal and in your project, install the&nbsp;<code>dotenv<\/code>&nbsp;module:<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<pre class=\"wp-block-code\"><code>npm install dotenv --save<\/code><\/pre>\n\n\n\n<div style=\"height:31px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Once this is installed, create a&nbsp;<code>.env<\/code>&nbsp;file in your project\u2019s root folder and store your access token in it using the format below:<\/p>\n\n\n\n<div style=\"height:31px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<pre class=\"wp-block-code\"><code> \/\/ .env\n\n    REACT_APP_ACCESS_TOKEN = Bearer YOUR_ACCESS_TOKEN_HERE<\/code><\/pre>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Fetching_data_with_hooks_and_Axios\"><\/span>Fetching data with hooks and Axios<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Once your access token is safely stored, you can use it to get promotion data from Reloadly\u2019s servers. First, define the variables you will need to use as headers when making a request for the promotion data. The code snippet blow shows how to achieve this:<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<pre class=\"wp-block-code\"><code> \/\/ src\/promotions.js\n\n    const accessToken = process.env.REACT_APP_ACCESS_TOKEN;\n    const reloadlyJSON = `application\/com.reloadly.topups-v1+json`\n    const headers = {\n      Accept: reloadlyJSON,\n      Authorization: accessToken\n    };<\/code><\/pre>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Next, you\u2019ll define and handle state management for various data interaction points in your application. The promotion tracker will use three variables to track its different states:<\/p>\n\n\n\n<ul><li><code>data<\/code>&nbsp;: For handling the promotion information retrieved from Reloadly\u2019s servers<\/li><li><code>countryCode<\/code>&nbsp;: For handling the country ISO code inputted by a user when requesting for promotion details about a particular country<\/li><li><code>loading<\/code>&nbsp;: For handling the time intervals between a request to Reloadly\u2019s servers and a response<\/li><\/ul>\n\n\n\n<p>These states can be managed with React\u2019s <code>useState()<\/code> hook. The code snippet blow shows how the <code>useState()<\/code> hook initializes and updates state in the data , countryCode and loading variables:<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<pre class=\"wp-block-code\"><code>    \/\/ src\/promotions.js\n\n    const &#91;data, setData] = useState(&#91;]);\n    const &#91;countryCode, setCountryCode] = useState(\"\");\n    const &#91;loading, setLoading] = useState(false);<\/code><\/pre>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Once this is done, you can make a&nbsp;<code>GET<\/code>&nbsp;request to Reloadly\u2019s \/promotions\/country-codes endpoint with the aid of Axios. The code snippet below shows how this can be achieved by creating an asynchronous function called&nbsp;<code>Promochecker()<\/code>&nbsp;and in it, making your request:<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<pre class=\"wp-block-code\"><code>\n\/\/ src\/promotions.js\n\n  const PromoChecker = async () => {\n    setLoading(true);\n    try {\n      await axios\n        .get(\n          `https:\/\/topups.reloadly.com\/promotions\/country-codes\/` + countryCode,\n          {\n            headers: headers\n          }\n        )\n        .then((res) => {\n          console.log(res.data)\n          setData(res.data);\n        });\n    } catch (e) {\n      setData(e.response.data);\n      console.log(e.response);\n    }\n    setLoading(false);\n  };<\/code><\/pre>\n\n\n\n<div style=\"height:31px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Viewing_an_operators_promotion_data\"><\/span>Viewing an operator\u2019s promotion data<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>The steps to fetching the promotion data of an operator have been outlined. However, this data needs to be displayed to users of your application. You will also need to display instructions on how to use the application. The achieve these, you will use React\u2019s&nbsp;<a href=\"https:\/\/reactjs.org\/docs\/conditional-rendering.html\">conditional rendering<\/a>&nbsp;feature to update the UI of your application. The code snippet below shows how you render a welcome message that will be seen by your application\u2019s users:<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<pre class=\"wp-block-code\"><code>\n\/\/ src\/promotions.js\n\nreturn (\n  &lt;section className=\"instructions\">\n    &lt;h1>Welcome!&lt;\/h1> &lt;br>&lt;\/br>{\" \"}\n    &lt;p>\n      You can search for ongoing promotions for mobile top-ups in a country by\n      using the country's Alpha 2 ISO code.\n    &lt;\/p>{\" \"}\n    &lt;br>&lt;\/br>\n    &lt;p>\n      {\" \"}\n      Refer to this{\" \"}\n      &lt;a\n        href=\"https:\/\/www.nationsonline.org\/oneworld\/country_code_list.htm\"\n        target=\"_blank\"\n        rel=\"noreferrer\"\n      >\n        page\n      &lt;\/a>{\" \"}\n      for a complete directory of ISO codes.\n    &lt;\/p>\n  &lt;\/section>\n);<\/code><\/pre>\n\n\n\n<div style=\"height:31px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Next, you need to display an input form to receive country codes from users. The code snippet below shows how this can be done via an input bar that receives search queries and updates the state of the&nbsp;<code>countryCode<\/code>&nbsp;variable with them:<\/p>\n\n\n\n<div style=\"height:32px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ src\/promotions.js\n\n&lt;section className=\"input_instructions\">\n &lt;input\n    type=\"text\"\n    placeholder=\"Enter country code...\"\n    onChange={(e) => setCountryCode(e.target.value)}\n  \/>\n...\n\n&lt;\/section><\/code><\/pre>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>After this, you\u2019ll create a button to handle user requests. Your button should be able to perform the following:<\/p>\n\n\n\n<ul><li>Launch a request to Reloadly\u2019s servers ( with the&nbsp;<code>PromoCheck()<\/code>&nbsp;function )<\/li><li>Display a spinner during the intervals of making a request and getting a response from Reloadly\u2019s servers ( with the&nbsp;<code>loading<\/code>&nbsp;variable\u2019s state )<\/li><\/ul>\n\n\n\n<p>The code snippet below depicts how this can be achieved with React\u2019s&nbsp;<code>onClick()<\/code>&nbsp;event handler and a ternary operator:<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ src\/promotions.js\n\n&lt;section className=\"input_instructions\">\n...\n\n  &lt;button className=\"btn\" onClick={PromoChecker} disabled={loading}>\n    {loading &amp;&amp; (\n      &lt;i\n        className=\"fa fa-refresh fa-spin\"\n        style={{ marginRight: \"5px\" }}\n      \/>\n    )}\n    {loading &amp;&amp; &lt;Spinner animation=\"border\" \/>}\n    {!loading &amp;&amp; &lt;span>Search&lt;\/span>}\n  &lt;\/button>\n&lt;\/section><\/code><\/pre>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>Basically, your home page should have the structure below ( excluding the styling ) when you are done:<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"543\" src=\"https:\/\/www.reloadly.com\/blog\/wp-content\/uploads\/2021\/09\/Screenshot-2021-09-27-124530-1024x543.jpg\" alt=\"\" class=\"wp-image-1820\" srcset=\"https:\/\/blog.reloadly.com\/blog\/wp-content\/uploads\/2021\/09\/Screenshot-2021-09-27-124530-1024x543.jpg 1024w, https:\/\/blog.reloadly.com\/blog\/wp-content\/uploads\/2021\/09\/Screenshot-2021-09-27-124530-300x159.jpg 300w, https:\/\/blog.reloadly.com\/blog\/wp-content\/uploads\/2021\/09\/Screenshot-2021-09-27-124530-768x407.jpg 768w, https:\/\/blog.reloadly.com\/blog\/wp-content\/uploads\/2021\/09\/Screenshot-2021-09-27-124530.jpg 1320w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>To display the information on promotions received as a response, you\u2019ll create an arrow function that maps through the promotion information in the&nbsp;<code>data<\/code>&nbsp;variable. The code snippet below shows how to achieve this using React Bootstrap components:<\/p>\n\n\n\n<div style=\"height:31px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ src\/promotions.js\n\n&lt;section className=\"response\">\n  {data.map((item) => (\n    &lt;Accordion key={item.id}>\n        &lt;Card className=\"response_card\">\n            &lt;Accordion.Toggle as={Card.Header} eventKey={item}>\n                {item.title} &lt;b>&amp;nbsp; &amp;nbsp; &amp;#8693;&lt;\/b>\n            &lt;\/Accordion.Toggle>\n            &lt;Accordion.Collapse eventKey={item}>\n                &lt;Card.Body>\n                  &lt;p>{item.denominations}&lt;\/p>\n                  &lt;p dangerouslySetInnerHTML={{ __html: item.description }}>&lt;\/p>\n                  &lt;p>{item.startDate}&lt;\/p>\n                  &lt;p>{item.endDate}&lt;\/p>\n              &lt;\/Card.Body>\n            &lt;\/Accordion.Collapse>\n        &lt;\/Card>\n    &lt;\/Accordion>\n  ))}\n&lt;\/section><\/code><\/pre>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>The key components of your application are all put up together now. Let\u2019s take a look at how it works when a user makes a request.<\/p>\n\n\n\n<div style=\"height:29px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<figure class=\"wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"api-request-to-view-promotions\" width=\"500\" height=\"375\" src=\"https:\/\/www.youtube.com\/embed\/KX8i9_B0D-g?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Summary\"><\/span>Summary<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Working with React Hooks provides a feasible way to handle data across different components. With Reloadly\u2019s REST API, you can retrieve data on telecom operators to meet your specific use case as shown in this article. You can check out the live demo of this application&nbsp;<a href=\"https:\/\/fullstackmafia.github.io\/reloadly-react-promotion-tracker\/\">here<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>All you need to know to build an application that checks for available airtime in any region of the world <\/p>\n","protected":false},"author":17,"featured_media":1831,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[274],"tags":[11,295,294,275],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v15.7 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Building a Promotion Tracker with React and Reloadly&#039;s API - Reloadly<\/title>\n<meta name=\"description\" content=\"Reloadly Resources. Insights, Info and Analysis For The Mobile Airtime API Community\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.reloadly.com\/blog\/building-a-promotion-tracker-with-react-and-reloadlys-api\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Building a Promotion Tracker with React and Reloadly&#039;s API - Reloadly\" \/>\n<meta property=\"og:description\" content=\"Reloadly Resources. Insights, Info and Analysis For The Mobile Airtime API Community\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.reloadly.com\/blog\/building-a-promotion-tracker-with-react-and-reloadlys-api\/\" \/>\n<meta property=\"og:site_name\" content=\"Reloadly\" \/>\n<meta property=\"article:published_time\" content=\"2021-09-27T12:14:30+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-10-05T11:33:16+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blog.reloadly.com\/blog\/wp-content\/uploads\/2021\/09\/react-cover-image.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1000\" \/>\n\t<meta property=\"og:image:height\" content=\"420\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\">\n\t<meta name=\"twitter:data1\" content=\"6 minutes\">\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.reloadly.com\/blog\/#organization\",\"name\":\"Reloadly\",\"url\":\"https:\/\/www.reloadly.com\/blog\/\",\"sameAs\":[],\"logo\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/www.reloadly.com\/blog\/#logo\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/blog.reloadly.com\/blog\/wp-content\/uploads\/2020\/11\/logo-1.svg\",\"width\":100,\"height\":100,\"caption\":\"Reloadly\"},\"image\":{\"@id\":\"https:\/\/www.reloadly.com\/blog\/#logo\"}},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.reloadly.com\/blog\/#website\",\"url\":\"https:\/\/www.reloadly.com\/blog\/\",\"name\":\"Reloadly\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/www.reloadly.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":\"https:\/\/www.reloadly.com\/blog\/?s={search_term_string}\",\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/www.reloadly.com\/blog\/building-a-promotion-tracker-with-react-and-reloadlys-api\/#primaryimage\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/blog.reloadly.com\/blog\/wp-content\/uploads\/2021\/09\/react-cover-image.jpg\",\"width\":1000,\"height\":420},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.reloadly.com\/blog\/building-a-promotion-tracker-with-react-and-reloadlys-api\/#webpage\",\"url\":\"https:\/\/www.reloadly.com\/blog\/building-a-promotion-tracker-with-react-and-reloadlys-api\/\",\"name\":\"Building a Promotion Tracker with React and Reloadly's API - Reloadly\",\"isPartOf\":{\"@id\":\"https:\/\/www.reloadly.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.reloadly.com\/blog\/building-a-promotion-tracker-with-react-and-reloadlys-api\/#primaryimage\"},\"datePublished\":\"2021-09-27T12:14:30+00:00\",\"dateModified\":\"2021-10-05T11:33:16+00:00\",\"description\":\"Reloadly Resources. Insights, Info and Analysis For The Mobile Airtime API Community\",\"breadcrumb\":{\"@id\":\"https:\/\/www.reloadly.com\/blog\/building-a-promotion-tracker-with-react-and-reloadlys-api\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.reloadly.com\/blog\/building-a-promotion-tracker-with-react-and-reloadlys-api\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.reloadly.com\/blog\/building-a-promotion-tracker-with-react-and-reloadlys-api\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"item\":{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.reloadly.com\/blog\/\",\"url\":\"https:\/\/www.reloadly.com\/blog\/\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"position\":2,\"item\":{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.reloadly.com\/blog\/building-a-promotion-tracker-with-react-and-reloadlys-api\/\",\"url\":\"https:\/\/www.reloadly.com\/blog\/building-a-promotion-tracker-with-react-and-reloadlys-api\/\",\"name\":\"Building a Promotion Tracker with React and Reloadly&#8217;s API\"}}]},{\"@type\":\"Article\",\"@id\":\"https:\/\/www.reloadly.com\/blog\/building-a-promotion-tracker-with-react-and-reloadlys-api\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.reloadly.com\/blog\/building-a-promotion-tracker-with-react-and-reloadlys-api\/#webpage\"},\"author\":{\"@id\":\"https:\/\/www.reloadly.com\/blog\/#\/schema\/person\/2400042054e3b3009489e487224a6984\"},\"headline\":\"Building a Promotion Tracker with React and Reloadly&#8217;s API\",\"datePublished\":\"2021-09-27T12:14:30+00:00\",\"dateModified\":\"2021-10-05T11:33:16+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.reloadly.com\/blog\/building-a-promotion-tracker-with-react-and-reloadlys-api\/#webpage\"},\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.reloadly.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.reloadly.com\/blog\/building-a-promotion-tracker-with-react-and-reloadlys-api\/#primaryimage\"},\"keywords\":\"airtime,javascript,react,reloadly\",\"articleSection\":\"Developer Blog\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.reloadly.com\/blog\/building-a-promotion-tracker-with-react-and-reloadlys-api\/#respond\"]}]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.reloadly.com\/blog\/#\/schema\/person\/2400042054e3b3009489e487224a6984\",\"name\":\"Raphael Ugwu\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/www.reloadly.com\/blog\/#personlogo\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/656844c0101d37e5695eee915ed3a49d?s=96&d=mm&r=g\",\"caption\":\"Raphael Ugwu\"},\"url\":\"https:\/\/blog.reloadly.com\/blog\/author\/fullstackmafia\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","authors":[{"term_id":359,"user_id":17,"is_guest":0,"slug":"fullstackmafia","display_name":"Raphael Ugwu"}],"_links":{"self":[{"href":"https:\/\/blog.reloadly.com\/blog\/wp-json\/wp\/v2\/posts\/1814"}],"collection":[{"href":"https:\/\/blog.reloadly.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.reloadly.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.reloadly.com\/blog\/wp-json\/wp\/v2\/users\/17"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.reloadly.com\/blog\/wp-json\/wp\/v2\/comments?post=1814"}],"version-history":[{"count":10,"href":"https:\/\/blog.reloadly.com\/blog\/wp-json\/wp\/v2\/posts\/1814\/revisions"}],"predecessor-version":[{"id":1908,"href":"https:\/\/blog.reloadly.com\/blog\/wp-json\/wp\/v2\/posts\/1814\/revisions\/1908"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.reloadly.com\/blog\/wp-json\/wp\/v2\/media\/1831"}],"wp:attachment":[{"href":"https:\/\/blog.reloadly.com\/blog\/wp-json\/wp\/v2\/media?parent=1814"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.reloadly.com\/blog\/wp-json\/wp\/v2\/categories?post=1814"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.reloadly.com\/blog\/wp-json\/wp\/v2\/tags?post=1814"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}