I’m creating bookshop application. I’m quite freshmen in programing world. Whole application is created in react.
My mission is to create modal component from existing "update" component.
The main component is books where is an update button, I would like the "Update" component to appear as a modal component after pressing "update – button" I have tried various ways to do this but I am stuck on this issue for good (2 days),
import React from "react";
import { useState, useEffect } from "react";
import axios from "axios";
import { Link } from "react-router-dom";
import "../style/style.css"
const Books = () => {
const [books, setBooks] = useState([]);
useEffect(() => {
const fetchAllBooks = async () => {
try {
const res = await axios.get("http://localhost:8800/books");
setBooks(res.data);
} catch (error) {
console.log(error);
}
};
fetchAllBooks();
}, []);
const handleDelete = async (id) => {
try {
await axios.delete(`http://localhost:8800/books/${id}`);
window.location.reload();
} catch (error) {
console.log(error);
}
};
return (
<div className="form">
<h1>The Greatest Bookshop</h1>
<div className="books">
{books.map((book) => (
<div
key={book.id}
className="book"
>
{book.cover && (
<img
className="mainImg"
src={book.cover}
alt=""
/>
)}
<h2>{book.title}</h2>
<p>{book.desc}</p>
<span>${book.price}</span>
<button
className="delete"
onClick={() => handleDelete(book.id)}
>
Delete
</button>
<button className="update">
<Link
to={`/update/${book.id}`}
style={{ color: "inherit", textDecoration: "none" }}
>
Update
</Link>
</button>
</div>
))}
</div>
<button className="newBook">
<Link
to="/Add"
style={{ color: "inherit", textDecoration: "none" }}
>
Add new book
</Link>
</button>
</div>
);
};
export default Books;
And component which need to be modal is "Update":
import React, { useState, useEffect, useRef } from "react";
import { useNavigate, useLocation } from "react-router-dom";
import axios from "axios";
import "../style/update.css";
// import EditCover from "../__Test__/EditCover";
const Update = () => {
const navigate = useNavigate();
const location = useLocation();
const bookId = location.pathname.split("/")[2];
const [book, setBook] = useState({
title: "",
desc: "",
price: null,
cover: "",
});
useEffect(() => {
const fetchCoverUrl = async () => {
try {
const res = await axios.get(`http://localhost:8800/books/${bookId}`);
setBook((prevBook) => ({ ...prevBook, cover: res.data[0].cover}));
} catch (error) {
console.log(error);
}
};
fetchCoverUrl();
}, [bookId]);
const fileInputRef = useRef(null);
const changeImage = () => {
fileInputRef.current.click();
};
const handleChange = (e) => {
setBook((prev) => ({ ...prev, [e.target.name]: e.target.value }));
};
const handleFileChange = (e) => {
const file = e.target.files[0];
setBook((prev) => ({...prev, cover: URL.createObjectURL(file),
}));
};
const handleClick = async (e) => {
e.preventDefault();
try {
await axios.put("http://localhost:8800/books/" + bookId, book);
navigate("/");
} catch (error) {
console.log(error);
}
};
return (
<div className="update-form">
<div className="update-container">
<h1>Update the Book</h1>
<input
type="text"
placeholder="title"
onChange={handleChange}
name="title"
/>
<input
type="text"
placeholder="desc"
onChange={handleChange}
name="desc"
/>
<input
type="number"
placeholder="price"
onChange={handleChange}
name="price"
/>
<input
data-id="inputRef"
type="file"
placeholder="cover"
ref={fileInputRef}
onChange={handleFileChange}
name="cover"
style={{display: "none"}}
/>
<button
className="updateBtn"
onClick={handleClick}
>
Update
</button>
</div>
<div className="coverForm">
{book.cover && (
<img
className="coverUpdate"
src={book.cover}
alt="Loading..."
onClick={changeImage}
style={{cursor: "pointer"}}
/>
)}
</div>
</div>
);
};
export default Update;
I am not really sure how i can figure existing "update" component to be a modal, i was basing on example:
import React, { useState } from 'react'
import "./test.css"
const ModalComponent = () => {
const [isModal, setIsModal] = useState(false);
const openModal = () => {
setIsModal(true);
}
const closeModal = () => {
setIsModal(false);
}
return (
<div>
<h1>Books</h1>
<button onClick={openModal}>Update</button>
{isModal && (
<div className="modal">
<div className="modal-content">
<h2>Update book</h2>
<button className="close-btn" onClick={closeModal}>Close</button>
</div>
</div>
)}
</div>
)
}
export default ModalComponent
2
Answers
You need to wrap
update
component inmodal-content
and open modal on click ofupdate
button.Creating a Modal using HTML CSS JS
You dont need to create a separate component for Modal if you only want to use this modal one time.
If you want the
Update
component content to open in theModalComponent
thenUpdate
should importModalComponent
and render the UI into it.ModalComponent
should be refactored a bit to take and render achildren
prop.Example:
Assume the modal is open by default when rendered/mounted, closed when unmounted.
From here you have a couple choices. You can import
ModalComponent
intoUpdate
and wrap directly the ui there:or you can create a layout route component that renders the
Update
route into the modal.