此问题已在此处有答案:
How to pass data from a page to another page using react router(5个答案)
18小时前关闭
我正在创建一个电子商务网站,我想做一个功能,如果用户点击一个特定的产品,用户应该能够看到该特定产品的产品详细信息。我想在react js中用react-router dom实现这个,我应该如何传递id并显示特定产品的细节
import "./HomeFurniture.scss";
import React, { useState, useEffect } from 'react';
import jsonData from '../../data.json';
import ProductCardContainer from '../../Component/Products/ProductCardContainer';
import TopHead from '../../Component/TopHead/TopHead';
import CustomSelect from '../../Component/TopHead/CustomSelect';
import { Link } from 'react-router-dom';
import { HiShoppingBag } from "react-icons/hi2";
const Bedroom = () => {
const [selectedOption, setSelectedOption] = useState('AtoZ');
const [category1Data, setCategory1Data] = useState([]);
useEffect(() => {
const bedroomProducts = jsonData.product.filter(product => product.category === 'Bedroom');
if (selectedOption === 'AtoZ') {
bedroomProducts.sort((a, b) => a.title.localeCompare(b.title));
} else if (selectedOption === 'ZtoA') {
bedroomProducts.sort((a, b) => b.title.localeCompare(a.title));
} else if (selectedOption === 'PriceLowToHigh') {
bedroomProducts.sort((a, b) => parseFloat(a.price.replace('$', '')) - parseFloat(b.price.replace('$', '')));
} else if (selectedOption === 'PriceHighToLow') {
bedroomProducts.sort((a, b) => parseFloat(b.price.replace('$', '')) - parseFloat(a.price.replace('$', '')));
}
setCategory1Data(bedroomProducts);
}, [selectedOption]);
const totalProductCards = category1Data.length;
const homeLink = <Link to="/">HOME</Link>;
const collectionlink = <Link to="/">Collection</Link>;
const bedroomLink = <Link to="/bedroom">Bedroom</Link>;
return (
<div className='furniture'>
<TopHead
tophead="Bedroom"
links={[homeLink, collectionlink, bedroomLink]}
/>
<div className='container'>
<div className='top-bed'>
<p className='furniture_header'>Showing {totalProductCards} products</p>
<CustomSelect selectedOption={selectedOption} setSelectedOption={setSelectedOption} />
</div>
</div>
<div className='container'>
{totalProductCards > 0 ? (
<div className="row">
{category1Data.map((item, index) => (
<ProductCardContainer
key={index}
title={item.title}
description={item.description}
description2={item.description2}
price={item.price}
img={item.img}
sku={item.sku}
availability={item.availability}
/>
))}
</div>
) : (
<div className="no-product ">
<HiShoppingBag className='shopping-bag' />
<p>There are no products!</p>
</div>
)}
</div>
</div>
);
}
export default Bedroom;
import React, { useState } from 'react';
import { ToastContainer, toast } from 'react-toastify';
import { Link } from 'react-router-dom';
import { GoGitCompare } from "react-icons/go";
import { AiOutlineHeart, AiFillHeart } from "react-icons/ai";
import { BsArrowsFullscreen, BsPlus, BsDash } from "react-icons/bs";
import 'react-toastify/dist/ReactToastify.css';
import Card from 'react-bootstrap/Card';
import Modal from 'react-bootstrap/Modal';
const ProductCardContainer = (props) => {
const [isInWishlist, setIsInWishlist] = useState(false);
const [isInCompare, setIsInCompare] = useState(false);
const [isHovered, setIsHovered] = useState(false);
const [modalShow, setModalShow] = useState(false);
const [counte, setCounte] = useState(0);
const toggleWishlist = () => {
setIsInWishlist(!isInWishlist);
if (!isInWishlist) {
toast.success('Added to wishlist!', {
position: 'top-right',
autoClose: 2000,
});
} else {
toast.error('Removed from wishlist!', {
position: 'top-right',
autoClose: 2000,
});
}
};
const toggleCompare = () => {
setIsInCompare(!isInCompare);
if (!isInCompare) {
toast.success('Added to Compare!', { position: 'top-right', autoClose: 2000 });
} else {
toast.error('Removed from Compare!', { position: 'top-right', autoClose: 2000 });
}
};
const incrementeCount = () => { setCounte(counte + 1) };
const decrementtCount = () => {
if (counte > 0) {
setCounte(counte - 1);
} else {
alert("0 aavi gyo chee..")
}
};
const handleMouseEnter = () => {
setIsHovered(true);
};
const handleMouseLeave = () => {
setIsHovered(false);
};
// const formattedTitle = props.id.replace(/ /g, '-');
const truncatedTitle = props.title.length > 26 ? `${props.title.substring(0, 26)}...` : props.title;
return (
<>
<div className="col-xl-3 col-md-6 col-ld-4 col-sm-6">
<div
className={`product-card ${isHovered ? 'hovered' : ''}`}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}>
<Card>
<div className='svg-icons'>
<span id="heart" className="heart" onClick={toggleWishlist}>
{isInWishlist ? <AiFillHeart /> : <AiOutlineHeart />}
</span>
{isHovered && (
<span className='button-svg'>
<BsArrowsFullscreen onClick={() => setModalShow(true)} />
<GoGitCompare onClick={toggleCompare} />
</span>
)}
</div>
{isHovered && (
<button className='form-btn-cart' onClick={toggleWishlist}>
{isInWishlist ? "Remove From Cart" : "Add To Cart"}
</button>
)}
<Card.Img variant="top" src={props.img} />
<Card.Body>
<Link to={`/product/${props.title}`} onClick={() => openProductDetail(props)}>
<h4>{props.price}</h4>
<Card.Title>{truncatedTitle}</Card.Title>
</Link>
</Card.Body>
</Card>
<ToastContainer />
</div>
</div>
{/* Modal */}
<Modal show={modalShow} onHide={() => setModalShow(false)}
size="lg"
aria-labelledby="contained-modal-title-vcenter"
centered>
<Modal.Header closeButton></Modal.Header>
<Modal.Body>
<div className="model-box">
<img src={props.img} alt={props.title} />
<div className="model-detail">
<p><strong>SKU : </strong> {props.sku}</p>
<p><strong>Availability : </strong>{props.availability}</p>
<h4>{props.title}</h4>
<p className='price'>{props.price}</p>
<p className='model-description'>{props.description}</p>
<div className="model-button">
<div className="timenum">
<button className="hookbtn" onClick={decrementtCount}><BsDash /></button>
<p className="hookh1">{counte} </p>
<button className="hookbtn" onClick={incrementeCount}><BsPlus /></button>
</div>
<div>
<button type="button" className='model_cart'>Add To Cart</button>
</div>
<div></div>
</div>
<div>
<div className='model-svg-icons'>
<span id="heart" className="heart" state={{ product: props }}>
{isInWishlist ? <AiFillHeart /> : <AiOutlineHeart />}
<p>Add To Wishlist</p>
</span>
<span id="heart" className="heart" onClick={toggleCompare}>
<GoGitCompare />
<p>Add To Compare</p>
</span>
</div>
</div>
</div>
</div>
</Modal.Body>
</Modal>
</>
);
};
export default ProductCardContainer;
import React from "react"
import {
createBrowserRouter,
RouterProvider,
Outlet
} from "react-router-dom";
import "./App.scss"
import Navbar from "./Component/Navbar/Navbar";
import Footer from "./Component/Footer/Footer";
import About from "./Pages/About/About";
import Contact from "./Pages/Contact/Contact";
import Bedroom from "./Pages/Home-Furniture/Bedroom";
import Dining from "./Pages/Home-Furniture/Dining";
import Living from "./Pages/Home-Furniture/Living";
import HospitalBed from "./Pages/Hospital-Furniture/HospitalBed";
import HospitalUtility from "./Pages/Hospital-Furniture/HospitalUtility";
import Lounge from "./Pages/Office-Furniture/Lounge";
import OfficeChair from "./Pages/Office-Furniture/OfficeChair";
import OfficeTable from "./Pages/Office-Furniture/OfficeTable";
import Home from "./Pages/Home/Home";
import SingleProduct from "./Component/Products/SingleProduct";
function App() {
const Layout = () => {
return (
<div className="app">
<Navbar />
<Outlet />
<Footer />
</div>
)
}
const router = createBrowserRouter([
{
path: "/",
element: <Layout />,
children: [
{
path: "/",
element: <Home />
},
{
path: "/about",
element: <About />
},
{
path: "/contact",
element: <Contact />
},
{
path: "/homefurniture/bedroom",
element: <Bedroom />
},
{
path: "/homefurniture/dining",
element: <Dining />
},
{
path: "/homefurniture/living",
element: <Living />
},
{
path: "/hospitalfurniture/hospitalbed",
element: <HospitalBed />
},
{
path: "/hospitalfurniture/hospitalutility",
element: <HospitalUtility />
},
{
path: "/officefurniture/lounge",
element: <Lounge />
},
{
path: "/officefurniture/officechair",
element: <OfficeChair />
},
{
path: "/officefurniture/officetable",
element: <OfficeTable />
},
{
path: `/product/:id`,
element: <SingleProduct />
}
]
}
])
return (
<>
<div>
<RouterProvider router={router} />
</div>
</>
)
}
export default App
singleproduct.js
import React, { useState } from 'react';
import "../TopHead/TopHead.scss";
import "./SingleProduct.scss";
import jsonData from '../../data.json';
import { useParams } from "react-router-dom"
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
import { GoGitCompare } from "react-icons/go";
import { AiOutlineHeart, AiFillHeart } from "react-icons/ai";
import { BsPlus, BsDash } from "react-icons/bs";
const SingleProductPage = () => {
const [isInWishlist, setIsInWishlist] = useState(false);
const [counte, setCounte] = useState(0);
const { productId } = useParams();
const thisProduct = jsonData.product.find(prod => prod.id === productId);
const toggleCompare = () => {
setIsInCompare(!isInCompare);
if (!isInCompare) {
toast.success('Added to Compare!', { position: 'top-right', autoClose: 2000 });
} else {
toast.error('Removed from Compare!', { position: 'top-right', autoClose: 2000 });
}
};
const incrementeCount = () => { setCounte(counte + 1) };
const decrementtCount = () => {
if (counte > 0) {
setCounte(counte - 1);
} else {
alert("0 aavi gyo chee..")
}
};
return (
<div className='topheading'>
<div className='top container-fluid'>
<h2>{thisProduct.title}</h2>
<ul>
<li className='sc-jVKKMF dYETTy'>badroom</li>
<li className='sc-jVKKMF dYETTy'>badroom</li>
<li className='sc-jVKKMF dYETTy'>badroom</li>
</ul>
</div>
<div className="bottom container">
<div className="model-box">
<img src="https://furns-react.netlify.app/_next/image?url=https%3A%2F%2Fcdn.shopify.com%2Fs%2Ffiles%2F1%2F0597%2F8970%2F5392%2Fproducts%2F11-02.jpg%3Fv%3D1632281991&w=384&q=75" />
<div className="model-detail">
<p><strong>SKU : </strong> </p>
<p><strong>Availability : </strong></p>
<h4>hgdkdnh fkwfwk</h4>
<p className='price'>234</p>
<p className='model-description'>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Inventore, natus placeat!
Beatae cupiditate in sunt omnis quos eius repudiandae itaque velit eveniet quae ratione, unde placeat id nihil doloremque ipsum.
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Soluta at ipsum voluptate laboriosam quasi? Omnis laudantium repudiandae,
quisquam debitis quaerat tempora velit sapiente fugiat modi ipsam perspiciatis tenetur magni saepe!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequuntur vel tempore ipsum minima doloribus dolore, assumenda corrupti illum
magni suscipit error amet blanditiis eius, debitis perferendis. Quod earum amet eaque.</p>
<div className="model-button">
<div className="timenum">
<button className="hookbtn" onClick={decrementtCount}><BsDash /></button>
<p className="hookh1">{counte} </p>
<button className="hookbtn" onClick={incrementeCount}><BsPlus /></button>
</div>
<div>
<button type="button" className='model_cart'>Add To Cart</button>
</div>
<div></div>
</div>
<div>
<div className='model-svg-icons'>
<span id="heart" className="heart">
{isInWishlist ? <AiFillHeart /> : <AiOutlineHeart />}
<p>Add To Wishlist</p>
</span>
<span id="heart" className="heart" onClick={toggleCompare}>
<GoGitCompare />
<p>Add To Compare</p>
</span>
</div>
</div>
</div>
</div>
</div>
<div className="revi-des">
<Tabs>
<TabList>
<Tab>
Description
</Tab>
<Tab >
Reviews
</Tab>
</TabList>
<TabPanel>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Eligendi voluptates nemo fugit sit excepturi ipsum quod, maxime ea numquam, placeat qui ipsa aspernatur nobis possimus vitae ducimus totam. Praesentium, deserunt.</p>
</TabPanel>
<TabPanel>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Eligendi quod officiis laudantium? Quaerat quam modi laborum explicabo dicta quibusdam atque suscipit consequatur voluptatem amet eum accusamus incidunt quo, inventore ipsa.
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quibusdam aut impedit sit in. Amet laudantium maiores modi sapiente similique possimus iure enim. Nemo minus tempore voluptatum laudantium temporibus totam in.
</p>
</TabPanel>
</Tabs>
</div>
</div>
)
};
export default SingleProductPage;
data.json
{
"product": [
{
"id": 1,
"category": "NewArrival",
"sku": "GXW",
"availability": "In Stock",
"title": "Variable Product",
"price": "$69.0",
"img": "https://furns-react.netlify.app/_next/image?url=https%3A%2F%2Fcdn.shopify.com%2Fs%2Ffiles%2F1%2F0597%2F8970%2F5392%2Fproducts%2F11-02.jpg%3Fv%3D1632281991&w=384&q=75",
"description": " Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repudiandae dicta, culpa quidem commodi id itaque labore placeat atque voluptatem quos accusantium, natus rem molestiae illum non ullam esse ut! Magnam. ",
},
{
"id": 2,
"category": "NewArrival",
"sku": "GXW",
"availability": "In Stock",
"title": "Josefa Queen Size Bed with Storage in Natural Teak Wood Finish",
"price": "$199.0",
"img": "https://furns-react.netlify.app/_next/image?url=https%3A%2F%2Fcdn.shopify.com%2Fs%2Ffiles%2F1%2F0597%2F8970%2F5392%2Fproducts%2F1.jpg%3Fv%3D1636862996&w=384&q=75",
"description": " Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repudiandae dicta, culpa quidem commodi id itaque labore placeat atque voluptatem quos accusantium, natus rem molestiae illum non ullam esse ut! Magnam. ",
},
{
"id": 3,
"category": "NewArrival",
"sku": "GXW",
"availability": "In Stock",
"title": "Minimalist Mid-Century Modern Style Bed",
"price": "$159.0",
"img": "https://furns-react.netlify.app/_next/image?url=https%3A%2F%2Fcdn.shopify.com%2Fs%2Ffiles%2F1%2F0597%2F8970%2F5392%2Fproducts%2F2.jpg%3Fv%3D1632544899&w=384&q=75",
"description": " Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repudiandae dicta, culpa quidem commodi id itaque labore placeat atque voluptatem quos accusantium, natus rem molestiae illum non ullam esse ut! Magnam. ",
},
{
"id": 4,
"category": "NewArrival",
"sku": "GXW",
"availability": "In Stock",
"title": "Twist Dining Table",
"price": "$49.0",
"img": "https://furns-react.netlify.app/_next/image?url=https%3A%2F%2Fcdn.shopify.com%2Fs%2Ffiles%2F1%2F0597%2F8970%2F5392%2Fproducts%2F1_d9913561-510c-4d82-8185-4e4fd3828742.jpg%3Fv%3D1632545251&w=384&q=75",
"description": " Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repudiandae dicta, culpa quidem commodi id itaque labore placeat atque voluptatem quos accusantium, natus rem molestiae illum non ullam esse ut! Magnam. ",
},
{
"id": 5,
"category": "NewArrival",
"sku": "GXW",
"availability": "In Stock",
"title": "Round Dining Table without chair",
"price": "$79.0",
"img": "https://furns-react.netlify.app/_next/image?url=https%3A%2F%2Fcdn.shopify.com%2Fs%2Ffiles%2F1%2F0597%2F8970%2F5392%2Fproducts%2F2_bb835864-60d7-4be5-8e85-cfee7c9f784d.jpg%3Fv%3D1632545382&w=384&q=75",
"description": " Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repudiandae dicta, culpa quidem commodi id itaque labore placeat atque voluptatem quos accusantium, natus rem molestiae illum non ullam esse ut! Magnam. ",
},
{
"id": 6,
"category": "NewArrival",
"sku": "GXW",
"availability": "In Stock",
"title": "Hospital Reception Table",
"price": "$129.0",
"img": "https://furns-react.netlify.app/_next/image?url=https%3A%2F%2Fcdn.shopify.com%2Fs%2Ffiles%2F1%2F0597%2F8970%2F5392%2Fproducts%2F1_6c997eeb-8f70-49d3-8432-0d82b2c83c8f.jpg%3Fv%3D1632547241&w=384&q=75",
"description": " Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repudiandae dicta, culpa quidem commodi id itaque labore placeat atque voluptatem quos accusantium, natus rem molestiae illum non ullam esse ut! Magnam. ",
},
{
"id": 7,
"category": "NewArrival",
"sku": "GXW",
"availability": "In Stock",
"title": "High back lounge office chairs",
"price": "$89.0",
"img": "https://furns-react.netlify.app/_next/image?url=https%3A%2F%2Fcdn.shopify.com%2Fs%2Ffiles%2F1%2F0597%2F8970%2F5392%2Fproducts%2F2_f43a8aeb-8572-4889-9c86-cc7914ee0649.jpg%3Fv%3D1632547434&w=384&q=75",
"description": " Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repudiandae dicta, culpa quidem commodi id itaque labore placeat atque voluptatem quos accusantium, natus rem molestiae illum non ullam esse ut! Magnam. ",
},
{
"id": 8,
"category": "NewArrival",
"sku": "GXW",
"availability": "In Stock",
"title": "Bedroom Exclusive Mattress",
"price": "$99.0",
"img": "https://furns-react.netlify.app/_next/image?url=https%3A%2F%2Fcdn.shopify.com%2Fs%2Ffiles%2F1%2F0597%2F8970%2F5392%2Fproducts%2F3.jpg%3Fv%3D1632547635&w=384&q=75",
"description": " Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repudiandae dicta, culpa quidem commodi id itaque labore placeat atque voluptatem quos accusantium, natus rem molestiae illum non ullam esse ut! Magnam. ",
},
{
"id": 9,
"category": "Featured",
"sku": "GXW",
"availability": "In Stock",
"title": "Variable Product",
"price": "$69.0",
"img": "https://furns-react.netlify.app/_next/image?url=https%3A%2F%2Fcdn.shopify.com%2Fs%2Ffiles%2F1%2F0597%2F8970%2F5392%2Fproducts%2F11-02.jpg%3Fv%3D1632281991&w=384&q=75",
"description": " Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repudiandae dicta, culpa quidem commodi id itaque labore placeat atque voluptatem quos accusantium, natus rem molestiae illum non ullam esse ut! Magnam. ",
},
{
"id": 10,
"category": "Featured",
"sku": "GXW",
"availability": "In Stock",
"title": "Twist Dining Table",
"price": "$49.0",
"img": "https://furns-react.netlify.app/_next/image?url=https%3A%2F%2Fcdn.shopify.com%2Fs%2Ffiles%2F1%2F0597%2F8970%2F5392%2Fproducts%2F1_d9913561-510c-4d82-8185-4e4fd3828742.jpg%3Fv%3D1632545251&w=384&q=75",
"description": " Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repudiandae dicta, culpa quidem commodi id itaque labore placeat atque voluptatem quos accusantium, natus rem molestiae illum non ullam esse ut! Magnam. ",
},
{
"id": 11,
"category": "Featured",
"sku": "GXW",
"availability": "In Stock",
"title": "High back lounge office chairs",
"price": "$89.0",
"img": "https://furns-react.netlify.app/_next/image?url=https%3A%2F%2Fcdn.shopify.com%2Fs%2Ffiles%2F1%2F0597%2F8970%2F5392%2Fproducts%2F2_f43a8aeb-8572-4889-9c86-cc7914ee0649.jpg%3Fv%3D1632547434&w=384&q=75",
"description": " Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repudiandae dicta, culpa quidem commodi id itaque labore placeat atque voluptatem quos accusantium, natus rem molestiae illum non ullam esse ut! Magnam. ",
},
{
"id": 12,
"category": "Featured",
"sku": "GXW",
"availability": "In Stock",
"title": "Round Dining Table without chair",
"price": "$79.0",
"img": "https://furns-react.netlify.app/_next/image?url=https%3A%2F%2Fcdn.shopify.com%2Fs%2Ffiles%2F1%2F0597%2F8970%2F5392%2Fproducts%2F2_bb835864-60d7-4be5-8e85-cfee7c9f784d.jpg%3Fv%3D1632545382&w=384&q=75",
"description": " Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repudiandae dicta, culpa quidem commodi id itaque labore placeat atque voluptatem quos accusantium, natus rem molestiae illum non ullam esse ut! Magnam. ",
},
{
"id": 13,
"category": "OnSale",
"sku": "GXW",
"availability": "In Stock",
"title": "Variable Product",
"price": "$69.0",
"img": "https://furns-react.netlify.app/_next/image?url=https%3A%2F%2Fcdn.shopify.com%2Fs%2Ffiles%2F1%2F0597%2F8970%2F5392%2Fproducts%2F11-02.jpg%3Fv%3D1632281991&w=384&q=75",
"description": " Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repudiandae dicta, culpa quidem commodi id itaque labore placeat atque voluptatem quos accusantium, natus rem molestiae illum non ullam esse ut! Magnam. ",
},
{
"id": 14,
"category": "OnSale",
"sku": "GXW",
"availability": "In Stock",
"title": "Twist Dining Table",
"price": "$49.0",
"img": "https://furns-react.netlify.app/_next/image?url=https%3A%2F%2Fcdn.shopify.com%2Fs%2Ffiles%2F1%2F0597%2F8970%2F5392%2Fproducts%2F2_bb835864-60d7-4be5-8e85-cfee7c9f784d.jpg%3Fv%3D1632545382&w=384&q=75",
"description": " Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repudiandae dicta, culpa quidem commodi id itaque labore placeat atque voluptatem quos accusantium, natus rem molestiae illum non ullam esse ut! Magnam. ",
},
如何在另一个页面上显示单个产品的详细信息?
1条答案
按热度按时间sqxo8psd1#
有很多选择你可以选择。
1.使用useNavigate钩子从产品列表页面发送产品的ID,然后使用useLocation钩子访问该页面上的ID。然后你可以把这个id发送到后端,它会给你给予具体的产品细节,然后你可以通过在react中填充值来向用户显示它。
1.使用相同的useNavigate钩子将整个对象发送到产品详细信息页面,在这种情况下,您不需要在后端发送请求,因为数据仅通过useNavigate进入状态。您可以使用useLocation再次访问数据。
如果你想使用这种方法,这里是有用的链接
https://dev.to/esedev/how-to-pass-and-access-data-from-one-route-to-another-with-uselocation-usenavigate-usehistory-hooks-1g5m