簡體   English   中英

ReactJs 產品詳情頁

[英]ReactJs Product Details Page

我有一個帶有有效Bearer令牌的API

我在產品頁面上列出了API中的所有三種產品。 我希望能夠在我創建的產品項目詳細信息頁面上單擊任何項目並顯示信息。

我已經成功創建了我的路線,我可以點擊並打開相關頁面。 現在的問題是在 ReactJS 中使用paramspropsmatch在項目詳細信息頁面上提取單個項目的詳細信息。

這是App.js文件

import "./index.scss";
import React from "react";
import {
  BrowserRouter as Router,
  Route,
  Routes,
} from "react-router-dom";

import Discover from "./pages/discover";
import ItemDetail from "./pages/itemDetail";

function App() {
  return (
    <Router>
      <Routes>
        <Route path="discover" exact element={<Discover />} />
        <Route path="/itemDetail/:productCode" exact element={<ItemDetail />} />
      </Routes>
    </Router>
  );
}

export default App;

這是產品頁面,我將其命名為發現我正在自定義卡片組件上呈現來自 API 的所有產品。

import React, { useState, useEffect } from "react";
import { Row, Col } from "react-bootstrap";
import StyledCard from "../components/Card";

const Discover = (props) => {
  const token = "3f224802-426e-3597-a2eb-7d35e6bff31d";
  const [result, setResult] = useState([]);

  useEffect(() => {
    fetch(
      "https://api.flash-internal.flash-group.com/ecommerceManagement/1.0.0/api/product/",
      {
        method: "GET",
        headers: { Authorization: `Bearer ${token}` },
      }
    )
      .then((res) => res.json())
      .then((json) => setResult(json));
  }, []);

  const cardStyle = {
    listStyle: "none",
    margin: 5,
    paddingLeft: 0,
    minWidth: 240,
  };
  return (
    <>
      <div className="latestdeals container my-5">
        <h1>All Products</h1>
        <Row className="hotcards">
          <Col className="colcard">
            {(result?.result || []).map((item) => (
              <div key={item.productCode} style={cardStyle}>
                <a href={`/itemDetail/${item.productCode}`}>
                  {" "}
                  <StyledCard
                    key={item.productCode}
                    name={item.vendor}
                    title={item.description}
                    price={item.value}
                  />
                </a>
              </div>
            ))}
          </Col>
        </Row>
      </div>
    </>
  );
};

export default Discover;

下面是項目詳細信息頁面,我想在其中顯示該 1 個特定項目中的所有數據。 我還想在將來將該商品添加到購物車(購物車頁面)。

import React, {useEffect, useState} from 'react';

function ItemDetail({ match }) {

    const [item, setItem] = useState({});
    const token = "3f224802-426e-3597-a2eb-7d35e6bff31d";

    useEffect(() => {
      fetch(
        "https://api.flash-internal.flash-group.com/ecommerceManagement/1.0.0/api/product/",
        {
          method: "GET",
          headers: { Authorization: `Bearer ${token}` },
        }
      )
        .then((res) => res.json())
        .then((json) => setItem(json));
    }, []);

    console.log(item);

  return (
    <div>Item Detail</div>
  )
}

export default ItemDetail;

下面終於是我從 API 得到的結果

{
    "result": [
        {
            "description": "PlayStation Store R50 Voucher ",
            "productCode": "317",
            "value": 50,
            "vendor": "Sony PlayStation"
        },
        {
            "description": "R1 - R2500 1Voucher Token",
            "productCode": "311",
            "value": 0,
            "vendor": "1Voucher"
        },
        {
            "description": "Refund 1Voucher Token",
            "productCode": "392",
            "value": 0,
            "vendor": "1Voucher"
        }
    ],
    "status": "Success"
}

問題

  • Discover組件正在呈現原始錨點 ( <a /> ) 標記,而不是react-router-dom提供的Link組件。 這將在單擊時重新加載頁面,丟失任何已保存的 React state。
  • ItemDetail不需要重新獲取與Discover相同的數據。 一個簡單的解決方案可能是將路由 state 中的特定項目發送到詳細信息頁面。

解決方案

發現

導入Link組件並用它替換錨標記。 在路由 state 中傳遞當前映射項。記住將響應result屬性保存到 state 而不是整個結果 object。

import { Link } from 'react-router-dom';

const Discover = (props) => {
  const token = "XXXXX";
  const [result, setResult] = useState([]);

  useEffect(() => {
    fetch(
      "https://api.flash-internal.flash-group.com/ecommerceManagement/1.0.0/api/product/",
      {
        method: "GET",
        headers: { Authorization: `Bearer ${token}` },
      }
    )
      .then((res) => res.json())
      .then((data) => setResult(data.result)); // <-- save data.result
  }, []);

  ...

  return (
    <div className="latestdeals container my-5">
      <h1>All Products</h1>
      <Row className="hotcards">
        <Col className="colcard">
          {result.map((item) => (
            <div key={item.productCode} style={cardStyle}>
              <Link // <-- use Link component
                to={`/itemDetail/${item.productCode}`}
                state={{ item }} // <-- pass item object in state
              >
                <StyledCard
                  key={item.productCode}
                  name={item.vendor}
                  title={item.description}
                  price={item.value}
                />
              </Link>
            </div>
          ))}
        </Col>
      </Row>
    </div>
  );
};

項目詳情

react-router-dom@6中, Route組件 API 與 v5 相比發生了一些變化,不再有任何route props ,即沒有historylocationmatch props。

ItemDetail是一個 function 組件,因此它可以使用 React 掛鈎,特別是useLocation掛鈎來訪問傳遞的路由 state。由於數據是在路由 state 中傳遞的,因此不需要額外的 GET 請求。

例子:

import React, {useEffect, useState} from 'react';
import { useLocation } from 'react-router-dom';

function ItemDetail() {
  const { state } = useLocation(); // <-- access route state

  const { item } = state || {}; // <-- unpack the item from state
    
  console.log(item);

  

  return item ? (
    <div>
      <p>{item.description]</p>
      <p>{item.productCode]</p>
      <p>{item.value]</p>
      <p>{item.vendor]</p>
    </div>
  ) : "No item matched/found.";
}

export default ItemDetail;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM