> For the complete documentation index, see [llms.txt](https://reactjs.koida.tech/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://reactjs.koida.tech/restful-apis-build-a-booksearch-app-ver-2.0/lesson-9-show-book-details-in-a-modal-working.md).

# 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`**

* **Objective**: Trigger the modal when the "Read More" button is clicked.
* **Key Changes**:
  * Added state `isModalOpen` to track the modal's visibility.
  * Added methods `handleOpenModal` and `handleCloseModal` to control the modal.
  * Included the `BookDetail` component conditionally.

**Explanation:**

* **State Management**:
  * `isModalOpen` ensures the modal only appears when needed.
* **Dynamic Rendering**:
  * `BookDetail` is only rendered when `isModalOpen` is `true`.

***

### ReadMore.jsx Component Update

{% tabs %}
{% tab title="Before Modal Display" %}

```jsx
// 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

```

{% endtab %}

{% tab title="After Modal Display" %}

````jsx
// 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

```
````

{% endtab %}
{% endtabs %}

#### **2. Create `BookDetail.jsx`**

* **Objective**: 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`:**

1. **Header**:
   * Displays the book title.
   * Includes a close button to exit the modal.
2. **Body**:
   * Shows book details like authors, published date, description, and publisher.
3. **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

{% tabs %}
{% tab title="BookDetail.jsx" %}

```jsx
// 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

```

{% endtab %}

{% tab title="Second Tab" %}

{% endtab %}
{% endtabs %}

#### **3. How It Works**

1. When the user clicks "Read More" in `ReadMore.jsx`:
   * `isModalOpen` is set to `true`, rendering `BookDetail`.
2. `BookDetail` displays the book's details in a Bootstrap-styled modal.
3. Clicking the "Close" button triggers the `onClose` callback:
   * This sets `isModalOpen` to `false`, hiding the modal.

***

#### **Benefits of This Approach**

1. **Reusability**:
   * The `BookDetail` component can be used in other parts of the app for similar functionality.
2. **Separation of Concerns**:
   * Modal logic is encapsulated in `BookDetail`, keeping `ReadMore` clean.
3. **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.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://reactjs.koida.tech/restful-apis-build-a-booksearch-app-ver-2.0/lesson-9-show-book-details-in-a-modal-working.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
