React30-Project 7: Building a Random Quote Generator with React.js, Redux Toolkit and Redux Thunk

Saurabh Mhatre
6 min readNov 6, 2023

--

Title Image

Introduction

In this tutorial, we’ll create a random quote generator using React.js, Redux Toolkit, and Redux Thunk. We’ll also learn how to use the useEffect hook to make API calls.

Goal

Make a random quote generation app using react hooks and redux-toolkit as shown below:

Try this project on your own before proceeding with solution below.

Using Redux Toolkit and Redux Thunk: Explained for beginners

Imagine You Have a Magical Notebook (Redux Store):

1. Basic Idea:
- Imagine you have a magical notebook (Redux store) where you write down important things you want to remember. This notebook is so special that anyone in your house can read and write in it.

2. Redux Toolkit (Magical Enhancements):
- Sometimes, you want to organize your notes better. Redux Toolkit is like getting magical sticky notes and tabs that help you keep things tidy in your notebook. It makes managing your notes (state) much easier.

3. Redux Thunk (Magical Helpers):
- Now, let’s say you need a friend’s help to write something in your notebook but only after they’ve done something important. Redux Thunk is like a magical friend who can do something special first before helping you write in your notebook.

Technically in React:

1. Creating the Magical Notebook (Redux Store):
- You set up a special notebook (Redux store) where you can keep all your important information (state).

 // This is like creating your magical notebook
import { configureStore } from '@reduxjs/toolkit';
import rootReducer from './reducers';
const store = configureStore({
reducer: rootReducer,
});

2. Organizing Your Notes (Using Redux Toolkit):
- Redux Toolkit provides tools to keep your notes (state) organized. It’s like getting magical sticky notes and tabs to make your notebook more user-friendly.

  // This is like getting magical sticky notes and tabs
import { createSlice } from '@reduxjs/toolkit';
const notesSlice = createSlice({
name: 'notes',
initialState: /* ... */,
reducers: {
/* ... */
},
});

3. Getting Help from a Magical Friend (Using Redux Thunk):
- Redux Thunk is like a magical friend who can do something special before helping you write in your notebook. It helps with asynchronous actions (tasks that take time).

 // This is like having a magical friend (Thunk) who can do special things
import { createAsyncThunk } from '@reduxjs/toolkit';
const fetchUser = createAsyncThunk('user/fetchUser', async () => {
/* ... */
});

In simple terms, Redux Toolkit is your special notebook that gets enhanced with organized features, and Redux Thunk is your magical friend who helps with special tasks. Together, they make managing your notes (state) in React much more delightful!

Now let’s get back to building our project:

Prerequisites

  • Node.js and npm installed on your system.
  • Basic understanding of JavaScript, React, Redux, and Redux Toolkit.

Step 1: Set Up a New React App

Open your terminal and run the following command to create a new React app:

npx create-react-app random-quote-generator-redux

Step 2: Install Redux Toolkit and Redux Thunk

In your terminal, navigate to the project directory and run the following commands to install Redux Toolkit and Redux Thunk:

npm install @reduxjs/toolkit react-redux redux-thunk

Step 3: Set Up Redux Store

Inside the src folder, create a new folder named slices. Inside this folder, create a file named quoteSlice.js with the following content:

import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";

export const fetchRandomQuote = createAsyncThunk(
"quote/fetchRandom",
async () => {
const response = await fetch("https://api.quotable.io/random");
const data = await response.json();
return data;
}
);

const quoteSlice = createSlice({
name: "quote",
initialState: {
quote: null,
status: "idle",
error: null
},
extraReducers: (builder) => {
builder
.addCase(fetchRandomQuote.pending, (state) => {
state.status = "loading";
})
.addCase(fetchRandomQuote.fulfilled, (state, action) => {
state.status = "succeeded";
state.quote = action.payload;
})
.addCase(fetchRandomQuote.rejected, (state, action) => {
state.status = "failed";
state.error = action.error.message;
});
}
});

export default quoteSlice.reducer;

Explanation:

We are creating a redux slice in which initialization, success and error state of API call.

Note: You can replace the random quote API URL with the one created in previous project in this series.

Step 4: Combine Reducers and Set Up Store

Inside the src folder, open the index.js file and update it with the following:

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { createStore, applyMiddleware } from "redux";
import { Provider } from "react-redux";
import rootReducer from "./slices/quoteSlice";
import thunk from "redux-thunk";

const store = createStore(rootReducer, applyMiddleware(thunk));

ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);

Explanation:

We are setting up redux store and passing rootReducer to initialize redux.

Step 5: Create a Quote Component

Inside the src folder, create a new component named Quote.js with the following content:

import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { fetchRandomQuote } from "./slices/quoteSlice";

const Quote = () => {
const dispatch = useDispatch();
const quote = useSelector((state) => state.quote);
const status = useSelector((state) => state.status);
useEffect(() => {
dispatch(fetchRandomQuote());
}, [dispatch]);
const handleFetchQuote = () => {
dispatch(fetchRandomQuote());
};

return (
<div className="card col-lg-6 col-md-6 col-10 d-flex justify-content-center">
<div className="heading">
{status === "loading" ? (
<div className="spinner-border text-secondary" role="status">
<span className="sr-only">Loading...</span>
</div>
) : null}
{quote && status !== "loading" ? <div>{quote.content}</div> : null}
</div>
<button
type="button"
className="btn btn-primary"
onClick={() => handleFetchQuote()}
>
<span>Generate Quote</span>
</button>
</div>
);
};

export default Quote;

Explanation:

We are getting state from redux using useSelector hook and dispatching redux actions using useDispatch hook.

Step 6: Create App Component

Open the App.js file and replace its content with the following:

import React from "react";
import "./App.css";
import Quote from "./Quote";

function App() {
return (
<div className="app row">
<Quote />
</div>
);
}

export default App;

Step 7: Add Some Basic Styling

Inside the src folder, create a file named App.css with the following content:

#root,
html,
body {
margin: 0;
padding: 0;
height: 100vh;
box-sizing: border-box;
}

.app {
height: 100%;
background: linear-gradient(rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.3)),
url("/images/nature.jpeg");
background-size: cover;
background-position: center;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
}

.card {
background: whitesmoke;
display: flex;
align-items: center;
flex-direction: column;
border-radius: 25px;
padding: 2%;
}

.heading {
display: flex;
align-items: center;
min-height: 40vh;
margin-bottom: 10px;
font-size: 24px;
}

Add bootstrap link in public/index.html head section:

<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z"
crossorigin="anonymous"
/>

Create a images folder in public folder and add image from below link for background image:
Background image

Step 8: Start the App

In your terminal, make sure you’re in the random-quote-generator-redux directory and run:

npm start

This will start the development server and open the app in your default web browser.

You should now see the app with a button to fetch a random quote. When you click the button, it will make an API call using Redux Thunk and display the quote.

Codesandbox link:
RandomQuoteGenerator-Codesandbox

Github link:
RandomQuoteGenerator-Github

Congratulations! You’ve successfully built a random quote generator using React.js, Redux Toolkit, and Redux Thunk, and learned how to use the useEffect hook to make API calls in React applications. Have a nice day ahead!

You can check out my Youtube channel for more content:
SaurabhNative-Youtube

Check out part 8 in the series for learning usage of react router below:-

React30-Part 8

--

--

Saurabh Mhatre
Saurabh Mhatre

Written by Saurabh Mhatre

Senior Frontend Developer with 9+ years industry experience. Content creator on Youtube and Medium. LinkedIn/Twitter/Instagram: @SaurabhNative

No responses yet