Lesson 9 - Show Book Details in a Modal - Working
Step-by-Step Implementation of Modal for Book Details
Objective
To create a modal that displays detailed book information using the BookDetail component. The modal is triggered when the "Read More" button in the ReadMore component is clicked.
Step 1. Modify ReadMore.jsx
ReadMore.jsxObjective: Trigger the modal when the "Read More" button is clicked.
Key Changes:
Added state
isModalOpento track the modal's visibility.Added methods
handleOpenModalandhandleCloseModalto control the modal.Included the
BookDetailcomponent conditionally.
Explanation:
State Management:
isModalOpenensures the modal only appears when needed.
Dynamic Rendering:
BookDetailis only rendered whenisModalOpenistrue.
ReadMore.jsx Component Update
// ReadMore.jsx - before modal display
// Import necessary libraries
import React, { useState } from 'react'
import PropTypes from 'prop-types'
const ReadMore = ({ text }) => {
const [isExpanded, setIsExpanded] = useState(false)
// Toggle the expanded state
const toggleExpanded = () => {
setIsExpanded(!isExpanded)
}
return (
<div>
{isExpanded ? (
<>
<p>{text}</p>
<button className="btn btn-secondary btn-sm" onClick={toggleExpanded}>
Close
</button>
</>
) : (
<>
<p>{text.length > 100 ? `${text.substring(0, 100)}...` : text}</p>
{text.length > 100 && (
<button className="btn btn-primary btn-sm" onClick={toggleExpanded}>
Read More
</button>
)}
</>
)}
</div>
)
}
// Define PropTypes for the component
ReadMore.propTypes = {
text: PropTypes.string.isRequired,
}
export default ReadMore
// ReadMoreUpdate.jsx - after modal display
// Import necessary libraries
import React, { useState } from 'react'
import PropTypes from 'prop-types'
import BookDetail from './BookDetail.jsx'
const ReadMore = ({ book }) => {
const [isModalOpen, setIsModalOpen] = useState(false)
// Open modal
const handleOpenModal = () => {
setIsModalOpen(true)
}
// Close modal
const handleCloseModal = () => {
setIsModalOpen(false)
}
return (
<div>
<button className="btn btn-primary btn-sm" onClick={handleOpenModal}>
Read More
</button>
{isModalOpen && <BookDetail book={book} onClose={handleCloseModal} />}
</div>
)
}
ReadMore.propTypes = {
book: PropTypes.shape({
title: PropTypes.string,
authors: PropTypes.arrayOf(PropTypes.string),
description: PropTypes.string,
publishedDate: PropTypes.string,
publisher: PropTypes.string,
}).isRequired,
}
export default ReadMore
```2. Create BookDetail.jsx
BookDetail.jsxObjective: A modal component that displays detailed book information with a "Close" button.
Bootstrap Modal Classes:
modal: Styles the modal dialog.modal-dialog: Centers the modal content.modal-content: Contains the modal structure (header, body, footer).btn-close: Provides a styled close button.
Structure of BookDetail:
Header:
Displays the book title.
Includes a close button to exit the modal.
Body:
Shows book details like authors, published date, description, and publisher.
Footer:
Includes a "Close" button to exit the modal.
Code Highlights:
Props:
book: Contains the book data to display.onClose: A callback function to handle modal closure.
Creation of BookDetail.jsx Component
// BookDetai;jsx
// Import necessary libraries
import React from 'react'
import PropTypes from 'prop-types'
import 'bootstrap/dist/css/bootstrap.min.css'
const BookDetail = ({ book, onClose }) => {
const { title, authors, publishedDate, description, publisher } = book.volumeInfo
return (
<div className="modal show d-block" tabIndex="-1" role="dialog">
<div className="modal-dialog" role="document">
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title">{title || 'No Title Available'}</h5>
<button
type="button"
className="btn-close"
onClick={onClose}></button>
</div>
<div className="modal-body">
<p>
<strong>Authors:</strong>{' '}
{authors ? authors.join(', ') : 'Unknown'}
</p>
<p>
<strong>Published Date:</strong> {publishedDate || 'Unknown'}
</p>
<p>
<strong>Description:</strong>{' '}
{description || 'No Description Available'}
</p>
<p>
<strong>Publisher:</strong> {publisher || 'Unknown'}
</p>
</div>
<div className="modal-footer">
<button
type="button"
className="btn btn-secondary"
onClick={onClose}>
Close
</button>
</div>
</div>
</div>
</div>
)
}
BookDetail.propTypes = {
book: PropTypes.shape({
title: PropTypes.string,
authors: PropTypes.arrayOf(PropTypes.string),
description: PropTypes.string,
publishedDate: PropTypes.string,
publisher: PropTypes.string,
}).isRequired,
onClose: PropTypes.func.isRequired,
}
export default BookDetail
3. How It Works
When the user clicks "Read More" in
ReadMore.jsx:isModalOpenis set totrue, renderingBookDetail.
BookDetaildisplays the book's details in a Bootstrap-styled modal.Clicking the "Close" button triggers the
onClosecallback:This sets
isModalOpentofalse, hiding the modal.
Benefits of This Approach
Reusability:
The
BookDetailcomponent can be used in other parts of the app for similar functionality.
Separation of Concerns:
Modal logic is encapsulated in
BookDetail, keepingReadMoreclean.
Responsive Design:
Bootstrap ensures the modal adapts to different screen sizes.
This implementation enhances the user experience by allowing detailed book information to be viewed without navigating away from the main page.
Last updated