我想使用 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));

};