我想使用 Reactjs 中的相同数据获取产品并在点击详细信息页面时发送它们
I want to Fetch products and send them on click to detail page with same data in Reactjs
I have fetched an fake api using fetch on ProductList.js file and when I click on any of the white hovered blocks I want to send the same data to ProductDetail.js. So for this I am checking the pathname and again fetching data on ProductDetail.js and matching the title using find method. So in the console I get the matched object but suddenly after that I get undefined in console. Check console. I have attached all the files for your reference and I am using Bootstrap@4.6.0 and json-server for fake api.
这是 index.js 文件,我在这里导入了 BrowserRouter。
#################Index.js#################
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
import "bootstrap/dist/css/bootstrap.min.css";
import "./index.css";
import App from "./App";
ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>,
document.getElementById("root")
);
这是 App.js 文件,我从这里发送 /:title
#################App.js#################
import React from "react";
import { Switch, Route } from "react-router";
import ProductList from "./components/ProductList";
import ProductDetail from "./components/ProductDetail";
import PageNotFound from "./components/PageNotFound";
const App = () => {
return (
<>
<Switch>
<Route exact={true} path="/" component={ProductList} />
<Route path="/:title" component={ProductDetail} />
<Route path="*" component={PageNotFound} />
</Switch>
</>
);
};
export default App;
我在这里使用 json-server 获取假 api 并显示列表并在白色悬停块上发送标题 onclick。加上css就知道了
#################ProductList.js#################
import React, { useState, useEffect } from "react";
import { Link } from "react-router-dom";
const API = "http://localhost:8000/data";
const ProductList = () => {
const [products, setProducts] = useState();
useEffect(() => {
getData();
}, []);
const getData = () => {
fetch(API)
.then((res) => res.json())
.then((data) => setProducts(data))
.catch((err) => console.log(err));
};
return (
<>
<div className="container">
<div className="row">
{products &&
products.map((item) => {
const { id, imageUrl } = item;
return (
<div key={id} className="col-sm-6">
<img className="img-fluid" src={imageUrl} alt="" />
<div className="box">
{item.details.map((item) => {
const classes = [
"",
"block1",
"block2",
"block3",
"block4",
"block5",
];
const { id, title, subTitle, price } = item;
return (
<div key={id} className={`white-block ${classes[id]}`}>
<i className="fa fa-circle"></i>
<Link to={`/${title}`}>
<div className="block">
<h5>{title}</h5>
<h6>{subTitle}</h6>
<p>Rs.{price}</p>
</div>
</Link>
</div>
);
})}
</div>
</div>
);
})}
</div>
</div>
</>
);
};
export default ProductList;
这里我通过 useLocation 路径名接收标题,我在 getProduct 函数中匹配标题。我收到 object 但突然我在控制台中变得未定义,不知道为什么,这就是我面临的问题。
#################ProductDetail.js#################
import React, { useState, useEffect } from "react";
import { Link } from "react-router-dom";
import { useLocation } from "react-router";
const ProductDetail = () => {
const [product, setProduct] = useState([]);
const { pathname } = useLocation();
useEffect(() => {
fetch("http://localhost:8000/data")
.then((res) => res.json())
.then((data) => {
setProduct((prev) => {
return { ...prev, mydata: data };
});
})
.catch((err) => console.log(err));
getProduct();
}, []);
console.log(product.mydata);
console.log(pathname);
const getProduct = () => {
if (product.mydata) {
product.mydata.map((item) => {
const x = item.details.find(
(items) => items.title === `${pathname.replace(/\|\//g, "")}`
);
console.log(x);
setProduct(x);
});
}
};
return (
<>
{product && (
<div className="container">
<div className="row">
<div className="col-lg-6">
<img
className="img-fluid"
src="https://www.ikea.com/ext/ingkadam/m/6f1cba42d7e45883/original/PH162921-crop001.jpg?f=s"
alt=""
/>
</div>
<div className="col-lg-6">
<h1>{product.title}</h1>
<h2>{product.subTitle}</h2>
<p>{product.price}</p>
<Link to="/">BACK</Link>
</div>
</div>
</div>
)}
</>
);
};
export default ProductDetail;
这是我的 db.json 文件。我正在使用 json-server
#################db.json#################
{
"data": [
{
"id": 1,
"imageUrl": "https://www.ikea.com/ext/ingkadam/m/6f1cba42d7e45883/original/PH162921-crop001.jpg?f=s",
"details": [
{
"id": 1,
"title": "Raw Pressery",
"subTitle": "Raw Sub Title",
"price": 111
},
{
"id": 2,
"title": "Wingreens",
"subTitle": "Wingreens Sub Title",
"price": 222
},
{
"id": 3,
"title": "Spice",
"subTitle": "Spice Sub Title",
"price": 333
},
{
"id": 4,
"title": "Impatient",
"subTitle": "Impatient Sub Title",
"price": 444
},
{ "id": 5, "title": "Boat", "subTitle": "Boat Sub Title", "price": 555 }
]
},
{
"id": 2,
"imageUrl": "https://www.ikea.com/ext/ingkadam/m/16daa9f360ad6234/original/PH177140.jpg?f=l",
"details": [
{
"id": 1,
"title": "Table",
"subTitle": "Table Sub Title",
"price": 1111
},
{
"id": 2,
"title": "Chair",
"subTitle": "Chair Sub Title",
"price": 2222
},
{
"id": 3,
"title": "Fridge",
"subTitle": "Fridge Sub Title",
"price": 3333
}
]
}
]
}
这是我的index.css。如果你添加这个 css 你会看到白色的悬停块。
#################index.css#################
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace;
}
.white-block {
position: absolute;
z-index: 9;
}
.block1 {
top: 2%;
left: 5%;
}
.block2 {
top: 15%;
left: 50%;
}
.block3 {
top: 40%;
left: 10%;
}
.block4 {
top: 50%;
right: 15%;
}
.block5 {
top: 70%;
left: 35%;
}
.fa-circle {
color: red;
}
.block {
background-color: white;
padding: 1rem;
opacity: 0;
}
.white-block:hover .block {
opacity: 1;
}
.showAll {
position: absolute;
bottom: 5%;
left: 10%;
z-index: 10;
}
fetch("http://localhost:8000/data")
.then((res) => res.json())
.then((data) => {
setProduct((prev) => {
return { ...prev, mydata: data };
});
})
.catch((err) => console.log(err));
getProduct();
问题出在这个代码块上。该代码将执行调用 fetch -> getProduct -> 运行 然后或捕获取决于 api 调用的结果。 getProduct() 应该是
const getProduct = () => {
fetch("http://localhost:8000/data")
.then((res) => res.json())
.then((data) => {
if (data && data.length > 0) {
data.map((item) => {
const x = item.details.find(
(items) => items.title === `${pathname.replace(/\|\//g, "")}`
);
console.log(x);
setProduct(x);
});
}
})
.catch((err) => console.log(err))
}
首先从 api 获取数据,然后获取该数据并像以前一样继续处理。
const getProduct = () => {
fetch("http://localhost:8000/data")
.then((res) => res.json())
.then((data) => {
if (data && data.length > 0) {
data.map((items) => {
const x = items.details.find((item) => {
return item.title === `${pathname.replace(/\|\//g, "")}`;
});
//Here I added a check if x has the value then only you set the product.
if (x) {
setProduct(x);
}
});
} else {
setProduct({});
}
})
.catch((err) => console.log(err));
};
I have fetched an fake api using fetch on ProductList.js file and when I click on any of the white hovered blocks I want to send the same data to ProductDetail.js. So for this I am checking the pathname and again fetching data on ProductDetail.js and matching the title using find method. So in the console I get the matched object but suddenly after that I get undefined in console. Check console. I have attached all the files for your reference and I am using Bootstrap@4.6.0 and json-server for fake api.
这是 index.js 文件,我在这里导入了 BrowserRouter。
#################Index.js#################
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
import "bootstrap/dist/css/bootstrap.min.css";
import "./index.css";
import App from "./App";
ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>,
document.getElementById("root")
);
这是 App.js 文件,我从这里发送 /:title
#################App.js#################
import React from "react";
import { Switch, Route } from "react-router";
import ProductList from "./components/ProductList";
import ProductDetail from "./components/ProductDetail";
import PageNotFound from "./components/PageNotFound";
const App = () => {
return (
<>
<Switch>
<Route exact={true} path="/" component={ProductList} />
<Route path="/:title" component={ProductDetail} />
<Route path="*" component={PageNotFound} />
</Switch>
</>
);
};
export default App;
我在这里使用 json-server 获取假 api 并显示列表并在白色悬停块上发送标题 onclick。加上css就知道了
#################ProductList.js#################
import React, { useState, useEffect } from "react";
import { Link } from "react-router-dom";
const API = "http://localhost:8000/data";
const ProductList = () => {
const [products, setProducts] = useState();
useEffect(() => {
getData();
}, []);
const getData = () => {
fetch(API)
.then((res) => res.json())
.then((data) => setProducts(data))
.catch((err) => console.log(err));
};
return (
<>
<div className="container">
<div className="row">
{products &&
products.map((item) => {
const { id, imageUrl } = item;
return (
<div key={id} className="col-sm-6">
<img className="img-fluid" src={imageUrl} alt="" />
<div className="box">
{item.details.map((item) => {
const classes = [
"",
"block1",
"block2",
"block3",
"block4",
"block5",
];
const { id, title, subTitle, price } = item;
return (
<div key={id} className={`white-block ${classes[id]}`}>
<i className="fa fa-circle"></i>
<Link to={`/${title}`}>
<div className="block">
<h5>{title}</h5>
<h6>{subTitle}</h6>
<p>Rs.{price}</p>
</div>
</Link>
</div>
);
})}
</div>
</div>
);
})}
</div>
</div>
</>
);
};
export default ProductList;
这里我通过 useLocation 路径名接收标题,我在 getProduct 函数中匹配标题。我收到 object 但突然我在控制台中变得未定义,不知道为什么,这就是我面临的问题。
#################ProductDetail.js#################
import React, { useState, useEffect } from "react";
import { Link } from "react-router-dom";
import { useLocation } from "react-router";
const ProductDetail = () => {
const [product, setProduct] = useState([]);
const { pathname } = useLocation();
useEffect(() => {
fetch("http://localhost:8000/data")
.then((res) => res.json())
.then((data) => {
setProduct((prev) => {
return { ...prev, mydata: data };
});
})
.catch((err) => console.log(err));
getProduct();
}, []);
console.log(product.mydata);
console.log(pathname);
const getProduct = () => {
if (product.mydata) {
product.mydata.map((item) => {
const x = item.details.find(
(items) => items.title === `${pathname.replace(/\|\//g, "")}`
);
console.log(x);
setProduct(x);
});
}
};
return (
<>
{product && (
<div className="container">
<div className="row">
<div className="col-lg-6">
<img
className="img-fluid"
src="https://www.ikea.com/ext/ingkadam/m/6f1cba42d7e45883/original/PH162921-crop001.jpg?f=s"
alt=""
/>
</div>
<div className="col-lg-6">
<h1>{product.title}</h1>
<h2>{product.subTitle}</h2>
<p>{product.price}</p>
<Link to="/">BACK</Link>
</div>
</div>
</div>
)}
</>
);
};
export default ProductDetail;
这是我的 db.json 文件。我正在使用 json-server
#################db.json#################
{
"data": [
{
"id": 1,
"imageUrl": "https://www.ikea.com/ext/ingkadam/m/6f1cba42d7e45883/original/PH162921-crop001.jpg?f=s",
"details": [
{
"id": 1,
"title": "Raw Pressery",
"subTitle": "Raw Sub Title",
"price": 111
},
{
"id": 2,
"title": "Wingreens",
"subTitle": "Wingreens Sub Title",
"price": 222
},
{
"id": 3,
"title": "Spice",
"subTitle": "Spice Sub Title",
"price": 333
},
{
"id": 4,
"title": "Impatient",
"subTitle": "Impatient Sub Title",
"price": 444
},
{ "id": 5, "title": "Boat", "subTitle": "Boat Sub Title", "price": 555 }
]
},
{
"id": 2,
"imageUrl": "https://www.ikea.com/ext/ingkadam/m/16daa9f360ad6234/original/PH177140.jpg?f=l",
"details": [
{
"id": 1,
"title": "Table",
"subTitle": "Table Sub Title",
"price": 1111
},
{
"id": 2,
"title": "Chair",
"subTitle": "Chair Sub Title",
"price": 2222
},
{
"id": 3,
"title": "Fridge",
"subTitle": "Fridge Sub Title",
"price": 3333
}
]
}
]
}
这是我的index.css。如果你添加这个 css 你会看到白色的悬停块。
#################index.css#################
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace;
}
.white-block {
position: absolute;
z-index: 9;
}
.block1 {
top: 2%;
left: 5%;
}
.block2 {
top: 15%;
left: 50%;
}
.block3 {
top: 40%;
left: 10%;
}
.block4 {
top: 50%;
right: 15%;
}
.block5 {
top: 70%;
left: 35%;
}
.fa-circle {
color: red;
}
.block {
background-color: white;
padding: 1rem;
opacity: 0;
}
.white-block:hover .block {
opacity: 1;
}
.showAll {
position: absolute;
bottom: 5%;
left: 10%;
z-index: 10;
}
fetch("http://localhost:8000/data")
.then((res) => res.json())
.then((data) => {
setProduct((prev) => {
return { ...prev, mydata: data };
});
})
.catch((err) => console.log(err));
getProduct();
问题出在这个代码块上。该代码将执行调用 fetch -> getProduct -> 运行 然后或捕获取决于 api 调用的结果。 getProduct() 应该是
const getProduct = () => {
fetch("http://localhost:8000/data")
.then((res) => res.json())
.then((data) => {
if (data && data.length > 0) {
data.map((item) => {
const x = item.details.find(
(items) => items.title === `${pathname.replace(/\|\//g, "")}`
);
console.log(x);
setProduct(x);
});
}
})
.catch((err) => console.log(err))
}
首先从 api 获取数据,然后获取该数据并像以前一样继续处理。
const getProduct = () => {
fetch("http://localhost:8000/data")
.then((res) => res.json())
.then((data) => {
if (data && data.length > 0) {
data.map((items) => {
const x = items.details.find((item) => {
return item.title === `${pathname.replace(/\|\//g, "")}`;
});
//Here I added a check if x has the value then only you set the product.
if (x) {
setProduct(x);
}
});
} else {
setProduct({});
}
})
.catch((err) => console.log(err));
};