Lesson 2 - BookShelf App Structure
Google BookShelf React App v1

App Structure
We are going to build Google Bookshelf React App with the following components:
Parent component : AppBookShelf.jsx contains three child components – NavBar.jsx, BookList.jsx and Footer.jsx. The children components are put in components folder.
Child components in components folder :
NavBar.jsx
: This component includes the application header title and theSearchBar.jsx
, both located in the same directory.BookList.jsx
: This component is responsible for displaying a list of book information fetched from an API endpoint. It accepts props for the title, authors, description, and publisher, as well as additional query props.Footer.jsx
: Contains copyright information along with social media links for Instagram, YouTube, Facebook, and X.
The code for the AppBookShelf.jsx
parent component
AppBookShelf.jsx
parent componentStep-by-Step Explanation for Students
Setup:
Import the required libraries and components.
Initialize the state variables using
useState
.
Fetch API Data:
Define
fetchBooks
to fetch and parse data from the Google Books API.Handle errors gracefully.
React Lifecycle:
Use
useEffect
to ensure the API is called when the component loads or whenquery
changes.
Handle User Input:
Define a function (
handleSearch
) to update thequery
based on user input.
Render the UI:
Divide the app into child components (
NavBar
,BookList
,Footer
) for better modularity.Pass props to child components to maintain communication between them.
Layout Structure of AppBookShelf Component
// Layout Design of AppBookShelf Component
AppBookShelf Component
│
├── State
│ ├── books (useState) - Array of fetched books
│ └── query (useState) - Search query string, default: 'react'
│
├── Methods
│ ├── fetchBooks() - Async function to fetch books from Google Books API
│ └── handleSearch() - Updates query state with new search term
│
├── Effects
│ └── useEffect - Calls fetchBooks when query changes
│
└── Render Structure
└── <div> (container mt-5)
├── <NavBar> - Navigation component
│ ├── Props:
│ │ ├── query - Current search query
│ │ └── onSearch - handleSearch callback
│
├── <BookList> - Book display component
│ ├── Props:
│ │ ├── books - Array of book data
│ │ └── query - Current search query
│
└── <Footer> - Footer component
//Pareant component in src folder : AppBookShelf.jsx
// Import necessary libraries and hooks
import React, { useState, useEffect } from 'react';
import NavBar from './components/NavBar';
import BookList from './components/BookList';
import Footer from './components/Footer';
import 'bootstrap/dist/css/bootstrap.min.css';
const AppBookShelf = () => {
// Step 1: Initialize state variables
const [books, setBooks] = useState([]); // Stores fetched book data
const [query, setQuery] = useState('react'); // Default query for API
// Step 2: Fetch books from the API
const fetchBooks = async () => {
try {
const response = await fetch(`https://www.googleapis.com/books/v1/volumes?q=${query}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
setBooks(data.items || []); // Update state with fetched books or an empty array
} catch (error) {
console.error('Error fetching books:', error);
}
};
// Step 3: Use useEffect to trigger fetchBooks on mount or query change
useEffect(() => {
fetchBooks();
}, [query]);
// Step 4: Handle query updates from child components
const handleSearch = (newQuery) => {
setQuery(newQuery);
};
return (
<div className="container mt-5">
{/* Step 5: Render the NavBar with props */}
<NavBar query={query} onSearch={handleSearch} />
{/* Step 6: Render the BookList with fetched data and query */}
<BookList books={books} query={query} />
{/* Step 7: Render the Footer */}
<Footer />
</div>
);
};
export default AppBookShelf;
Explanation of Code Structure
Explanation of AppBookShelf.jsx
Code Structure and Snippets
AppBookShelf.jsx
Code Structure and SnippetsThe code is structured step-by-step to make it easy for students to understand how the parent component manages data and communicates with its child components. Here's a detailed breakdown:
1. Importing Libraries and Components
import React, { useState, useEffect } from 'react';
import NavBar from './components/NavBar';
import BookList from './components/BookList';
import Footer from './components/Footer';
import 'bootstrap/dist/css/bootstrap.min.css';
React
: Core library for creating React components.useState
anduseEffect
: Hooks for managing state and side effects.Child Components:
NavBar
: Contains the search bar and header.BookList
: Displays the list of books.Footer
: Contains footer content (e.g., copyright and social links).
Bootstrap: A CSS framework for styling the app.
2. State Management
const [books, setBooks] = useState([]); // Stores the fetched book data
const [query, setQuery] = useState('react'); // Default search query
books
:Stores the array of books fetched from the API.
Initially set to an empty array.
query
:Stores the search term entered by the user.
Defaults to
"react"
to show results when the app first loads.
3. Fetching Data from the API End Point
const fetchBooks = async () => {
try {
const response = await fetch(`https://www.googleapis.com/books/v1/volumes?q=${query}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
setBooks(data.items || []); // Update books state with fetched data
} catch (error) {
console.error('Error fetching books:', error);
}
};
API Endpoint:
Fetches book data using the search term stored in
query
.
Steps:
Makes an HTTP GET request using
fetch
.Checks if the response is successful (
response.ok
).Parses the response JSON and updates the
books
state.Handles errors with
try...catch
.
4. Using useEffect
for Side Effects
useEffect(() => {
fetchBooks();
}, [query]);
Purpose:
Automatically fetches data when the component mounts or when the
query
state changes.
Dependency Array:
[query]
ensures the function re-runs only when the search term changes.
5. Handling Search Input
const handleSearch = (newQuery) => {
setQuery(newQuery); // Updates the query state with the new input
};
Functionality:
Called back when the user enters a new search term.
Updates the
query
state, which triggersuseEffect
to fetch new data.
6. Rendering the Component - NavBar, BookList, Footer components
return (
<div className="container mt-5">
<NavBar query={query} onSearch={handleSearch} />
<BookList books={books} query={query} />
<Footer />
</div>
);
Container: The entire app is wrapped in a Bootstrap container for layout.
Child Components:
NavBar
:Receives
query
andhandleSearch
as props.Displays the header and search bar.
BookList
:Receives
books
andquery
as props.Dynamically displays the list of books fetched from the API.
Footer
:Displays footer content like copyright and social media links.
Bootstrap Integration
Classes:
container
: Ensures a responsive layout.mt-5
: Adds top margin for spacing.
Provides a clean and professional look without writing custom CSS.
Outcome
By following these steps:
Students can understand how to manage data and user interactions in a React app.
They learn how to fetch, manage, and display data from an external API.
They gain insight into component-based architecture and modular design.
Last updated