React - Random Quote Machine with Image!

Hello everyone;

I spent my entire day building a picture-filled random quote machine.

Initially, it didn’t seem so challenging; I thought I’d do some web scraping to grab the relevant author’s picture and do something unique. Then I realized that using Wikipedia for suitable images was the best approach — until I discovered that Wikipedia had an API. Oh, how I wish I hadn’t found out! That’s when I started grappling with the most challenging and complex API I’ve ever encountered. Fetching the image directly or from its URL seemed impossible, or perhaps I just couldn’t manage it. The documentation wasn’t quite sufficient, or maybe I couldn’t figure out the format to get the desired result from the documentation. At first, I managed to create a very elegant search API endpoint as described in the documentation. But then I gave up and simply inserted the author’s name into the search URLs I found :grin::see_no_evil:

const fetchQuoteData = async () => {
      const quoteData = randomquoteApi.randomQuote();
      setQuote(quoteData);
      const url = `https://en.wikipedia.org/w/api.php?action=query&generator=search&gsrsearch=${quoteData.author}&gsrlimit=5&prop=pageimages|extracts&exchars=25&exintro&explaintext&exlimit=max&format=json&origin=*`;

I tried to locate the matching page by searching for the author, then I had to retrieve the page image using a separate API call.

The hardest part was finding a single page to match; for some authors, it was impossible. For instance, searching for John F. Kennedy might return John F. Kennedy Airport... I tried various approaches, fetching multiple results and selecting the best match. I changed my search method, compared string characters, implemented a scoring system, but it didn’t work. Finally, I discovered a package called “string-similarity” that provided the most consistent results. However, the problem wasn’t over yet; I found that the API’s data mostly returned the ID of the first element in the “pages” property as -1 — sometimes random numbers. Of course, I couldn’t initially realize this; I only discovered it when I was trying to debug why Muhammad Ali’s picture wasn’t showing up… There were many bugs and issues along the way. At one point, I found myself reading the documentation for the HTML anchor element :see_no_evil:

Finally, it’s done. Of course, it’s possible to achieve the same task with a much better, more elegant code structure, but this is all I could manage. I was so focused on the JavaScript part that I had no energy left for new design or anything related to CSS. I borrowed the design from a sample project and wrote the CSS in a straightforward manner without much thought.

For now, everything seems to be working okay. Seneca occasionally causes issues, but there’s nothing I can do about that; I’m not a big fan of his philosophy anyway. And also sometimes some author’s image little bit irrelevant… Oh, and sometimes Britney Spears lyrics pop up; I respect those who love her, but let’s face it, they don’t pair well after Einstein :rofl:. Maybe if I brainstormed a bit, I could impose a ban on certain authors… Anyway, that’s enough for now…

I just wanted to share; of course, I’d greatly appreciate any feedback. I’m particularly curious if there are better solutions for finding images and matching them to authors :grin:.

Happy coding, everyone!

Hi @0x74h51N

Great rqm.

Try let bestMatchScore = 0; in async function processWikiData

It may run slower, but the accuracy of the image goes up.

Happy coding

Thank you :blush:. I haven’t encountered any matching errors or incorrect photos in string-similarity version yet. However, there are some loading time issues due to making two fetch requests—one for matching and another for fetching large Wikipedia images—which is why I initialized bestMatchScore to -1 :see_no_evil:. Sometimes certain photos take too long to load or aren’t found, so I added an extra check for this using onLoad.

Here are some mismatched images and quote authors.
I didn’t encounter any image / author pair failing to load.

Maybe increase the number of colour transitions while the data is fetched?

image
image
image
image

Okay, I found that bug with try speed limit, after you showed… Yes you will not encounter a failure to load because I implemented a time check for this. If an image takes too much time to load, it attempts to refetch the quote and images. If the image loads same or close time with 2700ms (which previously failed to load), it still triggers the following block but image didn’t change or something like that :see_no_evil::

  useEffect(() => {
    const timeout = setTimeout(() => {
      if (!imageLoaded) {
        console.log("Image load timeout, fetching new quote...");
        handleClick();
      }
    }, 2700);

May be I can handle it with a shorter timeout, but it may still not be stable. The issue is not related to mismatched fetching; it is related to large photos taking a long time to load… :see_no_evil:

Also I tried thumbnail images for fast load but they looks really bad :see_no_evil:

Or maybe I can optimize by periodically querying and requesting images in the background to store them in the browser’s cache. This way, they can load faster when they appear in subsequent quotes. :thinking:

How about a smaller size for the thumbnail?

EDIT: try 50% smaller thumbnail.
image

Yea I tried it gives very bad resolution :see_no_evil:

No, still not good enough :see_no_evil:. I also tried this:

But it’s a bit overkill for this small app :sweat_smile: