React30-Project 7: Building a Random Quote Generator with React.js, Redux Toolkit and Redux Thunk
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:-