Building a Quote Generator: Challenges and Lessons

I started learning how to code on freeCodeCamp in March 2021. From then until September 2021, I was pretty consistent with my learning. During that time, I completed the Responsive Web Design Certification and moved on to the next certification in the curriculum, JavaScript Algorithms and Data Structures.

I got stuck on the last project of this second certification, the Cash Register project. After battling with this project for a while, I decided to move on to the next certification, Front End Development Libraries.

I completed the interactive lessons without much hassle. It was time to build the projects, the first of which was the Random Quote Machine, but I didn’t know how to proceed. It seemed like I had learned nothing from the lessons. I decided to work on the other projects and come back later to the Quote Generator, but it was the same story.

Ultimately, I realised that I needed more resources to pull off these projects, so I began learning React on YouTube, depending mostly on John Smilga’s courses on the freeCodeCamp channel. Due to some circumstances, I didn’t complete any of the videos. But I always had in mind to return to those freeCodeCamp projects and complete them.

Almost two years later, in August 2023, I was back again on YouTube viewing John Smilga’s React 18 course. I completed this one, the over 14-hour-long video. Then I went back to the freeCodeCamp website to continue from where I stopped two years ago.

How I built the Random Quote Machine is the subject of this article. I’ll describe my process, dwelling more on the challenges I encountered, lessons learned and possible next steps, without giving much away to anyone who intends to try out the project.

CONTENTS

  • Introduction

  • Prerequisites

  • Technologies and third-party services used

  • Workflow

  • Challenges

  • Next steps

  • Conclusion

Introduction

The quote generator (I prefer this name to the verbose random quote machine) is a web app that displays a new quote on a button click. It also has a button to share the generated quote on Twitter.

This is not a how-to article, as I wouldn’t want to spoil the fun for anyone who may want to undertake building this app. My aim is just to share my process, not necessarily to teach how I built it.

Prerequisites

To follow along with the article, especially the section on Workflow, you need a basic knowledge of:

  • JavaScript (ES6)

  • the ReactJS library

Technologies and third-party services used

Besides React and CSS, I used the following technologies and/or third-party services for this project:

Workflow

I used the Vite local development server to install the starter files for the project. After launching the React app and making sure that changes in the App.jsx file reflected on the screen, my routine was to pick a particular feature and implement it.

I began by studying the Quotes API documentation. When I felt I’d understood how the API works, I proceeded to test it out in the App.jsx file. I logged the response of the API call to the console to have a full picture.

// some code
const displayQuote = async () => {
  const resp = await axios({
    url: "https://api.api-ninjas.com/v1/quotes",
    headers: { "X-Api-Key": "bdH0ad6RQC1YLqvfnOyogQ==SsiqwgM4LOP2vD9S" },
  });
  console.log(resp);
};
// more code

The response is an object, and the property of interest is the data property.

Inspecting the response of the API call

This data property is an array of 1 item. This item is an object with the following properties: quote, author and category.

Having understood the nature of the response, I imported React’s useState hook and set up the quote state and the setQuote function.

import { useState } from "react";

function App() {
  const [quote, setQuote] = useState({
    quote: "It does not matter how slowly you go as long as you do not stop.",
    author: "Confucius",
    category: "growth",
  });
  // more code
}

I relied on the format of resp.data[0] in the console to provide default values for the quote, author and category properties.

Next, I set up the JSX, populating the relevant HTML elements with the quote and author. I also set the onClick event on the .new-quote button equal to the displayQuote function.

return (
    <>
      <main style={{ color: color }} className="quote-box">
        <div className="quote">
          <p className="text">&quot;{quote.quote}&quot;</p>
          <p className="author">– {quote.author}</p>
        </div>
        <div className="btn-share">
          <button
            type="button"
            onClick={displayQuote}
            className="new-quote"
          >
            new quote
          </button>
        </div>
      </main>
    </>
  );

With the display new quote feature working properly, it was time to face the tweet quote functionality. This was the first real challenge I encountered, as I wasn’t sure how to implement it. So, I googled twitter share button react. The search results included some articles on the react-share library, a library I didn’t know about. This library makes it possible to share your web app (or a part of it) on Social Media (Facebook, Twitter and/or Instagram). The results page also showed a resource on Tweet Web Intent, which was what I finally used.

<a
  className="tweet-quote"
  href={`https://twitter.com/intent/tweet?text="${quote.quote}"%0D%0D${quote.author}&hashtags=quote,${quote.category}`}
  target="_blank"
  rel="noreferrer"
  style={{ backgroundColor: color }}
 >
   <TweetIcon />
 </a>

At this point, the quote generator was practically complete. What was left was to add some CSS to improve the visual appeal, but I wouldn’t dwell on that.

Challenges

In addition to implementing the share quote on Twitter feature, I encountered the following challenges while building this quote generator:

  • The background colour of the entire app changes with the quotes. Implementing this feature wasn’t straightforward, since I needed to set it up on the <body> element. React template files, as far as I know, are organised in such a way that the <body> element is part of the index.html file, and I had virtually no work to do in this file. My workaround was to use Vanilla JS to manipulate the <body> element in the App.jsx file.
const [color, setColor] = useState("#F39BA3");
document.body.style = `background: ${color};`;
  • Changing the colour of the tweet icon was also challenging. I found out from my research that changing the fill attribute of the <path> child element of the <svg> element would give the desired result.
<svg
    xmlns="http://www.w3.org/2000/svg"
    height="1em"
    viewBox="0 0 512 512"
>
    <path
        d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"
        fill="white"
    />
</svg>

Next steps

Several alternatives were available to me while building this app.

For state management, I could have used either the useRef hook or the Redux toolkit instead of the useState hook. My choice of useState came down to the fact that there weren’t too many state values. Also, as this is my first React app, it made sense to go for the more common useState. There will definitely be opportunities in future to use useRef and Redux.

I’ve hinted in an earlier section that I could have used the react-share library instead of the Tweet Web Intent. To get some practice with this library, I may incorporate functionality to share the quotes on Facebook and Instagram.

Conclusion

I enjoyed working on this Quote Generator app. It is my first React app. Building this app really improved my knowledge of React and CSS. It wasn’t without its challenges, but I’m happy I persevered until the end. While there is room for improvement, I’m proud of my achievement.

You can see the app here and the GitHub repo here.