英文:
Modal component in React
问题
I can help you with translating the non-code parts of your text. Here's the translation:
"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),"
If you have any specific questions or need further assistance, please feel free to ask.
英文:
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
答案1
得分: 0
你需要将 update
组件包装在 modal-content
中,并在点击 update
按钮时打开模态框。
如果你只想使用这个模态框一次,就不需要创建一个单独的模态框组件。
英文:
You need to wrap update
component in modal-content
and open modal on click of update
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.
答案2
得分: 0
如果你想让 Update
组件的内容在 ModalComponent
中打开,那么 Update
应该导入 ModalComponent
并将 UI 渲染到其中。ModalComponent
应该进行一些重构以接受和渲染一个 children
属性。
示例:
假设模态框在渲染/挂载时默认打开,在卸载时关闭。
const ModalComponent = ({ children, onClose }) => {
return (
<div className="modal">
<div className="modal-content">
<button className="close-btn" onClick={onClose}>Close</button>
{children}
</div>
</div>
);
};
从这里你有两个选择。你可以将 ModalComponent
导入到 Update
中并直接包裹 UI:
import React, { useState, useEffect, useRef } from "react";
import { useNavigate, useLocation, useParams } from "react-router-dom";
import axios from "axios";
import "../style/update.css";
// import EditCover from "../__Test__/EditCover";
import { ModalComponent } from "../path/to/ModalComponent";
const Update = () => {
const navigate = useNavigate();
const location = useLocation();
const { bookId } = useParams();
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]);
...
return (
<ModalComponent onClose={() => navigate(-1)}> // <-- 返回到列表
<div className="update-form">
<div className="update-container">
...
</div>
...
</div>
</ModalComponent>
);
};
export default Update;
或者你可以创建一个布局路由组件,将 Update
路由渲染到模态框中。
import { Outlet, useNavigate } from "react-router-dom";
import { ModalComponent } from "../path/to/ModalComponent";
const UpdateLayout = () => {
const navigate = useNavigate();
return (
<ModalComponent onClose={() => navigate(-1)}>
<Outlet />
</ModalComponent>
);
};
<Routes>
...
<Route element={<UpdateLayout />}>
<Route path="/update/:bookId" element={<Update />} />
</Route>
...
</Routes>
英文:
If you want the Update
component content to open in the ModalComponent
then Update
should import ModalComponent
and render the UI into it. ModalComponent
should be refactored a bit to take and render a children
prop.
Example:
Assume the modal is open by default when rendered/mounted, closed when unmounted.
const ModalComponent = ({ children, onClose }) => {
return (
<div className="modal">
<div className="modal-content">
<button className="close-btn" onClick={onClose}>Close</button>
{children}
</div>
</div>
);
};
From here you have a couple choices. You can import ModalComponent
into Update
and wrap directly the ui there:
import React, { useState, useEffect, useRef } from "react";
import { useNavigate, useLocation, useParams } from "react-router-dom";
import axios from "axios";
import "../style/update.css";
// import EditCover from "../__Test__/EditCover";
import { ModalComponent } from "../path/to/ModalComponent";
const Update = () => {
const navigate = useNavigate();
const location = useLocation();
const { bookId } = useParams();
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]);
...
return (
<ModalComponent onClose={() => navigate(-1)}> // <-- navigate back to list
<div className="update-form">
<div className="update-container">
...
</div>
...
</div>
</ModalComponent>
);
};
export default Update;
or you can create a layout route component that renders the Update
route into the modal.
import { Outlet, useNavigate } from "react-router-dom";
import { ModalComponent } from "../path/to/ModalComponent";
const UpdateLayout = () => {
const navigate = useNavigate();
return (
<ModalComponent onClose={() => navigate(-1)}>
<Outlet />
</ModalComponent>
);
};
<Routes>
...
<Route element={<UpdateLayout />}>
<Route path="/update/:bookId" element={<Update />} />
</Route>
...
</Routes>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论