Build a Simple React JS Interactive Web-Based Random Quote Generator: A Beginner’s Guide

In the digital age, we’re constantly bombarded with information, and sometimes, a little dose of inspiration can go a long way. Imagine a web application that serves up random, uplifting quotes with a simple click. This isn’t just a fun project; it’s a practical exercise in understanding the core concepts of React JS. Building a random quote generator allows you to practice state management, API calls, and component composition in a tangible way. This tutorial will guide you, step-by-step, through creating your own interactive quote generator, perfect for beginners and intermediate developers looking to hone their React skills.

Why Build a Random Quote Generator?

Beyond the motivational aspect, building a random quote generator is a fantastic learning experience. It gives you hands-on practice with:

  • State Management: You’ll learn how to store and update data (the quotes) within your application.
  • API Consumption: You’ll fetch data from an external API, a crucial skill for any web developer.
  • Component Composition: You’ll break down your application into reusable components.
  • Event Handling: You’ll learn how to respond to user interactions, such as button clicks.

This project is also an excellent way to familiarize yourself with React’s fundamental concepts without getting bogged down in complex features. By the end of this tutorial, you’ll have a fully functional application and a solid understanding of how React works.

Prerequisites

Before we dive in, ensure you have the following:

  • Node.js and npm (or yarn) installed: These are essential for managing your project’s dependencies and running the development server.
  • Basic understanding of HTML, CSS, and JavaScript: Familiarity with these languages is crucial for understanding the code and styling the application.
  • A code editor: Choose your favorite – VS Code, Sublime Text, Atom, or any other editor you prefer.

Step 1: Setting Up Your React Project

Let’s get started by creating a new React project using Create React App. Open your terminal and run the following command:

npx create-react-app random-quote-generator

This command creates a new directory called `random-quote-generator` with all the necessary files to start your React application. Navigate into the project directory:

cd random-quote-generator

Now, start the development server:

npm start

This command will open your application in your default web browser, usually at `http://localhost:3000`. You should see the default React welcome screen.

Step 2: Cleaning Up the Boilerplate

Before we start coding our quote generator, let’s clean up the boilerplate code provided by Create React App. Open the `src` directory in your code editor. You’ll find several files. We’ll focus on the following:

  • `src/App.js`: This is the main component of your application.
  • `src/App.css`: This file contains the styles for your application.
  • `src/index.js`: This file renders your `App` component into the DOM.

Let’s modify `src/App.js` to remove the default content and prepare for our quote generator. Replace the contents of `src/App.js` with the following:


import React from 'react';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <h1>Random Quote Generator</h1>
      </header>
      <main>
        <p>Click the button below to get a random quote.</p>
        <button>New Quote</button>
      </main>
    </div>
  );
}

export default App;

Also, clear the contents of `src/App.css`. We’ll add our own styles later.

Step 3: Fetching Quotes from an API

To get random quotes, we’ll use a free and publicly available API. There are several options; this tutorial uses Quotable API. This API provides a simple endpoint to retrieve a random quote.

We’ll use the `useEffect` hook to fetch the quote when the component mounts. Modify your `App.js` file as follows:


import React, { useState, useEffect } from 'react';
import './App.css';

function App() {
  const [quote, setQuote] = useState('');
  const [author, setAuthor] = useState('');

  useEffect(() => {
    async function fetchQuote() {
      try {
        const response = await fetch('https://api.quotable.io/random');
        const data = await response.json();
        setQuote(data.content);
        setAuthor(data.author);
      } catch (error) {
        console.error('Error fetching quote:', error);
        setQuote('Failed to fetch quote.');
        setAuthor('');
      }
    }

    fetchQuote();
  }, []); // The empty dependency array ensures this effect runs only once on mount

  return (
    <div className="App">
      <header className="App-header">
        <h1>Random Quote Generator</h1>
      </header>
      <main>
        <p>{quote}</p>
        <p>- {author}</p>
        <button>New Quote</button>
      </main>
    </div>
  );
}

export default App;

In this code:

  • We import `useState` and `useEffect` from React.
  • We initialize two state variables: `quote` and `author`, using `useState`. These variables will hold the quote text and the author’s name, respectively.
  • The `useEffect` hook is used to fetch the quote from the API when the component mounts.
  • Inside `useEffect`, we define an asynchronous function `fetchQuote` to make the API call.
  • We use `fetch` to get data from the API endpoint.
  • The response is converted to JSON using `response.json()`.
  • The `content` and `author` properties from the API response are used to update the `quote` and `author` state variables using `setQuote` and `setAuthor`.
  • We include a `try…catch` block to handle potential errors during the API call. If an error occurs, we log it to the console and display an error message.
  • The empty dependency array `[]` in `useEffect` ensures that the API call is made only once when the component mounts, preventing infinite loops.
  • Finally, we display the `quote` and `author` in the `main` section of our application.

Step 4: Adding a Button to Fetch New Quotes

Currently, the quote is fetched only when the component mounts. Let’s add a button that allows the user to fetch a new quote on demand. Modify `App.js` again:


import React, { useState, useEffect } from 'react';
import './App.css';

function App() {
  const [quote, setQuote] = useState('');
  const [author, setAuthor] = useState('');

  useEffect(() => {
    fetchQuote(); // Call fetchQuote initially
  }, []); // Remove dependency array

  const fetchQuote = async () => {
    try {
      const response = await fetch('https://api.quotable.io/random');
      const data = await response.json();
      setQuote(data.content);
      setAuthor(data.author);
    } catch (error) {
      console.error('Error fetching quote:', error);
      setQuote('Failed to fetch quote.');
      setAuthor('');
    }
  };

  return (
    <div className="App">
      <header className="App-header">
        <h1>Random Quote Generator</h1>
      </header>
      <main>
        <p>{quote}</p>
        <p>- {author}</p>
        <button onClick={fetchQuote}>New Quote</button>
      </main>
    </div>
  );
}

export default App;

Changes in this step:

  • We removed the empty dependency array from useEffect.
  • We moved the `fetchQuote` function outside of `useEffect` so that we can call it from the button.
  • We added an `onClick` event handler to the button. When the button is clicked, it calls the `fetchQuote` function.

Now, when you click the “New Quote” button, a new quote will be fetched and displayed.

Step 5: Styling Your Quote Generator

Let’s add some styling to make our quote generator look better. Open `src/App.css` and add the following CSS:


.App {
  text-align: center;
  font-family: sans-serif;
  background-color: #f0f0f0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 20px;
}

.App-header {
  background-color: #282c34;
  color: white;
  padding: 20px;
  border-radius: 5px;
  margin-bottom: 20px;
}

.App-header h1 {
  margin: 0;
}

main {
  background-color: white;
  padding: 20px;
  border-radius: 5px;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
  max-width: 600px;
}

main p {
  font-size: 1.2rem;
  line-height: 1.6;
  margin-bottom: 15px;
}

button {
  background-color: #61dafb;
  color: white;
  border: none;
  padding: 10px 20px;
  border-radius: 5px;
  cursor: pointer;
  font-size: 1rem;
  transition: background-color 0.2s ease;
}

button:hover {
  background-color: #4ba0c9;
}

This CSS provides basic styling for the entire application, the header, the main content area, and the button. Feel free to customize the styles to your liking. Experiment with different colors, fonts, and layouts to create a visually appealing quote generator.

Step 6: Handling Errors Gracefully

In the `fetchQuote` function, we’ve already included a `try…catch` block to handle potential errors during the API call. However, let’s improve the user experience by providing more informative error messages. Modify the `fetchQuote` function in `App.js` as follows:


const fetchQuote = async () => {
  try {
    const response = await fetch('https://api.quotable.io/random');
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    const data = await response.json();
    setQuote(data.content);
    setAuthor(data.author);
  } catch (error) {
    console.error('Error fetching quote:', error);
    setQuote('Failed to fetch quote. Please try again later.');
    setAuthor('');
  }
};

Changes in this step:

  • We added a check using `if (!response.ok)` to handle HTTP errors (e.g., 404 Not Found, 500 Internal Server Error).
  • If the response is not ok, we throw a new error with a descriptive message including the HTTP status code.
  • The `catch` block now displays a more user-friendly error message.

This ensures that the user receives a helpful message if something goes wrong with the API call.

Step 7: Adding a Loading State (Optional, but Recommended)

To enhance the user experience further, we can add a loading state while the quote is being fetched. This provides visual feedback to the user that something is happening. Modify `App.js` as follows:


import React, { useState, useEffect } from 'react';
import './App.css';

function App() {
  const [quote, setQuote] = useState('');
  const [author, setAuthor] = useState('');
  const [isLoading, setIsLoading] = useState(false);

  useEffect(() => {
    fetchQuote(); // Call fetchQuote initially
  }, []);

  const fetchQuote = async () => {
    setIsLoading(true);
    try {
      const response = await fetch('https://api.quotable.io/random');
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      const data = await response.json();
      setQuote(data.content);
      setAuthor(data.author);
    } catch (error) {
      console.error('Error fetching quote:', error);
      setQuote('Failed to fetch quote. Please try again later.');
      setAuthor('');
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <div className="App">
      <header className="App-header">
        <h1>Random Quote Generator</h1>
      </header>
      <main>
        {isLoading ? (
          <p>Loading...</p>
        ) : (
          <>
            <p>{quote}</p>
            <p>- {author}</p>
          </>
        )}
        <button onClick={fetchQuote} disabled={isLoading}>New Quote</button>
      </main>
    </div>
  );
}

export default App;

Changes in this step:

  • We added a new state variable, `isLoading`, initialized to `false`.
  • Inside `fetchQuote`, we set `setIsLoading(true)` before making the API call.
  • We use a `finally` block to set `setIsLoading(false)` regardless of whether the API call succeeds or fails. This ensures that the loading state is always cleared.
  • In the `main` section, we conditionally render either a “Loading…” message or the quote and author, based on the `isLoading` state.
  • We disable the “New Quote” button while `isLoading` is true to prevent multiple API calls at once.

Now, when you click the button, you’ll see a “Loading…” message while the quote is being fetched, providing a smoother user experience.

Step 8: Deploying Your Quote Generator

Once you’ve built your quote generator, you’ll likely want to share it with the world. There are several ways to deploy a React application. Here’s a simple method using Netlify:

  1. Create a GitHub Repository: Initialize a Git repository in your project directory (if you haven’t already) and push your code to GitHub. This is crucial for deploying with Netlify.
  2. Sign Up for Netlify: If you don’t already have an account, sign up for a free Netlify account at netlify.com.
  3. Connect Your GitHub Repository: In your Netlify dashboard, click “Add new site” and choose “Deploy from Git”. Connect your GitHub account and select the repository you created for your quote generator.
  4. Configure the Build Settings: Netlify will automatically detect that it’s a React project. The default build settings should work fine, but you can verify them. The “Build command” should be `npm run build` or `yarn build`, and the “Publish directory” should be `build`.
  5. Deploy Your Site: Click “Deploy site”. Netlify will build your project and deploy it to a unique URL.
  6. Custom Domain (Optional): You can connect a custom domain to your Netlify site if you have one.

That’s it! Your quote generator is now live and accessible to anyone with the URL provided by Netlify.

Common Mistakes and How to Fix Them

Here are some common mistakes beginners make when building React applications, along with how to fix them:

  • Incorrect import paths: Double-check your import statements. Make sure you’re importing components, modules, and CSS files from the correct locations. Use relative paths (e.g., `./App.css`) and ensure the file names match exactly.
  • Unnecessary re-renders: Avoid unnecessary re-renders of your components. Use `React.memo` or `useMemo` to optimize performance if your component is re-rendering too often. Review your component’s dependencies in `useEffect` and ensure they are correct.
  • Incorrect state updates: When updating state using `useState`, make sure you’re updating the state correctly. If the new state depends on the previous state, use a function in `setQuote` like `setQuote(prevQuote => prevQuote + ‘new text’)`.
  • Missing dependencies in `useEffect` : If your `useEffect` hook relies on any variables from outside the hook, include those variables in the dependency array (the second argument of `useEffect`). Failing to do so can lead to unexpected behavior.
  • Network request errors: Always handle network request errors gracefully using `try…catch` blocks. Provide informative error messages to the user.
  • Not cleaning up `useEffect` : If your `useEffect` hook sets up subscriptions or event listeners, remember to clean them up in the return function of `useEffect` to avoid memory leaks.

Key Takeaways

  • You’ve learned how to create a basic React application using Create React App.
  • You’ve practiced fetching data from a public API using `useEffect` and `fetch`.
  • You’ve learned how to manage state using `useState`.
  • You’ve gained experience with component composition.
  • You’ve learned how to handle user interactions with the `onClick` event.
  • You’ve learned how to style your React components using CSS.
  • You’ve learned how to deploy your React application using Netlify.

FAQ

  1. How can I change the quote API? You can easily change the API by modifying the URL in the `fetch` call within the `fetchQuote` function. Make sure the new API provides a similar response format (e.g., a quote and an author).
  2. How do I add more styling? You can add more styling by modifying the `src/App.css` file. You can use CSS, CSS Modules, or a CSS-in-JS solution.
  3. How can I add social sharing buttons? You can add social sharing buttons by using a third-party library or creating your own. You’ll need to generate the shareable URLs for each social media platform (e.g., Twitter, Facebook).
  4. How can I make the app responsive? Use media queries in your CSS to make the app responsive. You can adjust the layout and styles based on the screen size.
  5. How do I add animations? You can use CSS animations or a JavaScript animation library like `react-spring` to add animations to your quote generator.

Building a random quote generator is a stepping stone to more complex React projects. You can extend this project by adding features such as categories of quotes, a favorite quotes feature (using local storage), or the ability to share quotes on social media. Remember to break down complex problems into smaller, manageable parts. Practice consistently, and you’ll continue to improve your React skills. The journey of a thousand lines of code begins with a single component. Keep building, keep learning, and keep coding – the world of React awaits your creations.