簡體   English   中英

為什么在我的 React 應用程序中無法獲取 function

[英]Why the fetch function does not work from my React app

我正在通過使用 Js、React 和 express/post-gres DB 來學習全棧 我已經在 localhost:5003 上設置了服務器,服務器端 app.js 是

const express = require("express");
const cors = require("cors");
const app = express();
const data = require("./products.json");
const getTotalProducts = require("./repository");

app.use(cors());

app.get("/api", (req, res) => {
  res.status(200).send("Hello from API server");
});

app.get("/products", async (req, res) => {
   const totalProducts = await getTotalProducts();
   res.send(data.products);
});

module.exports = app;

products.json 有十個產品是

{"products":[
    {"id":1,"name":"Angel Wings Harness","description":"The purrrfect accessory to take your kitty to the next level.","price":"$10.00","categoryName":"Accessories","imageName":"cat-photo_0000.jpg","imageDescription":"Wings harness","discountValue":10,"discountType":"percentage off"},
    {"id":2,"name":"Deluxe Carry Bag Orange","description":"Backpack-style carry bag with dome.","price":"$20.00","categoryName":"Accessories","imageName":"cat-photo_0001.jpg","imageDescription":"Carry Bag Deluxe","discountValue":null,"discountType":null},
    {"id":3,"name":"KittyLove Apron Red","description":"Puff-look apron to protect against dinner time oopsies.","price":"$15.00","categoryName":"Accessories","imageName":"cat-photo_0002.jpg","imageDescription":"Apron","discountValue":null,"discountType":null},
    {"id":4,"name":"Outta Space Dome Carry Bag Yellow","description":"Dome-style re-inforced plastic carry bag.","price":"$30.00","categoryName":"Accessories","imageName":"cat-photo_0003.jpg","imageDescription":"Carry Bag Dome","discountValue":null,"discountType":null},
    {"id":5,"name":"McMeowful Soft Bow Collar Baby Pink","description":"Hypo-allergenic bow with ultrasoft-style security clip for extra comfort.","price":"$40.00","categoryName":"Accessories","imageName":"cat-photo_0004.jpg","imageDescription":"Stylish Bow Collar","discountValue":null,"discountType":null},
    {"id":6,"name":"Jumper Grandad-style Grey","description":"Grandad-style jumper from soft merino wool with button-style clips.","price":"$5.00","categoryName":"Tops","imageName":"cat-photo_0005.jpg","imageDescription":"Jumper Grandad Style","discountValue":null,"discountType":null},
    {"id":7,"name":"PartyTime Soldier Outfit Khaki","description":"Party-style soldier outfit, one size fits all.","price":"$100.00","categoryName":"Party outfits","imageName":"cat-photo_0006.jpg","imageDescription":"Soldier Outfit","discountValue":null,"discountType":null},
    {"id":8,"name":"PartyTime Sailor Outfit Small","description":"Party-style sailor outfit, size small.","price":"$70.00","categoryName":"Party outfits","imageName":"cat-photo_0007.jpg","imageDescription":"Sailor Outfit","discountValue":null,"discountType":null},
    {"id":9,"name":"Angel Wings","description":"The purrrfect accessory to take your kitty to the next level.","price":"$10.00","categoryName":"Accessories","imageName":"cat-photo_0015.jpg","imageDescription":"Wings harness","discountValue":15,"discountType":"fixed amount off"},
    {"id":10,"name":"Deluxe Carry Bag Red","description":"Backpack-style carry bag with dome.","price":"$20.00","categoryName":"Accessories","imageName":"cat-photo_0008.jpg","imageDescription":"Carry Bag Deluxe","discountValue":null,"discountType":null}]
}

啟動服務器后,我使用“Insomnia”檢查我的 GET 請求“http:localhost:3002/products”的響應,我可以將所有產品發回。現在我將在瀏覽器中呈現它們使用 React。客戶端 App.js 看起來像

import "./App.css";
import { React, useState, useEffect } from "react";
import Product from "./components/product";

const App = () => {
  const [products, setProducts] = useState(null);
  useEffect(() => {
    const fetchData = async () => {
      const response = await fetch("http://localhost:5003/products");
      const data = await response.json();
      setProducts(data.products);
      };
    fetchData();
  }, []);
   
  return (
    <div>
      {products.map((product) => (
        <Product
          name={product.name}
          img={product.imageName}
          description={product.description}
          price={product.price}
        />
      ))}
    </div>
  );
};

export default App;

從這里我沒有在頁面上呈現任何東西,它沒有觸發提取 function 我認為 - 因為在瀏覽器開發者工具中我沒有看到 GET 請求已被觸發。在瀏覽器控制台中也有很多警報消息顯示在那里

react-dom.development.js:86 Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot
printWarning @ react-dom.development.js:86
error @ react-dom.development.js:60
render @ react-dom.development.js:29404
./src/index.js @ index.js:7
options.factory @ react refresh:6
__webpack_require__ @ bootstrap:24
(anonymous) @ startup:7
(anonymous) @ startup:7
App.js:16 after fetch the products is null
App.js:16 after fetch the products is null
App.js:18 Uncaught TypeError: Cannot read properties of null (reading 'map')
    at App (App.js:18:1)
    at renderWithHooks (react-dom.development.js:16141:1)
    at mountIndeterminateComponent (react-dom.development.js:20838:1)
    at beginWork (react-dom.development.js:22342:1)
    at HTMLUnknownElement.callCallback (react-dom.development.js:4157:1)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:4206:1)
    at invokeGuardedCallback (react-dom.development.js:4270:1)
    at beginWork$1 (react-dom.development.js:27243:1)
    at performUnitOfWork (react-dom.development.js:26392:1)
    at workLoopSync (react-dom.development.js:26303:1)
App @ App.js:18
renderWithHooks @ react-dom.development.js:16141
mountIndeterminateComponent @ react-dom.development.js:20838
beginWork @ react-dom.development.js:22342
callCallback @ react-dom.development.js:4157
invokeGuardedCallbackDev @ react-dom.development.js:4206
invokeGuardedCallback @ react-dom.development.js:4270
beginWork$1 @ react-dom.development.js:27243
performUnitOfWork @ react-dom.development.js:26392
workLoopSync @ react-dom.development.js:26303
renderRootSync @ react-dom.development.js:26271
performSyncWorkOnRoot @ react-dom.development.js:25924
flushSyncCallbacks @ react-dom.development.js:11982
flushSync @ react-dom.development.js:26040
legacyCreateRootFromDOMContainer @ react-dom.development.js:29309
legacyRenderSubtreeIntoContainer @ react-dom.development.js:29335
render @ react-dom.development.js:29419
./src/index.js @ index.js:7
options.factory @ react refresh:6
__webpack_require__ @ bootstrap:24
(anonymous) @ startup:7
(anonymous) @ startup:7
react-dom.development.js:18525 The above error occurred in the <App> component:

    at App (http://localhost:3001/static/js/bundle.js:34:82)

Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
logCapturedError @ react-dom.development.js:18525
update.callback @ react-dom.development.js:18558
callCallback @ react-dom.development.js:13092
commitUpdateQueue @ react-dom.development.js:13113
commitLayoutEffectOnFiber @ react-dom.development.js:23204
commitLayoutMountEffects_complete @ react-dom.development.js:24461
commitLayoutEffects_begin @ react-dom.development.js:24447
commitLayoutEffects @ react-dom.development.js:24385
commitRootImpl @ react-dom.development.js:26651
commitRoot @ react-dom.development.js:26517
performSyncWorkOnRoot @ react-dom.development.js:25956
flushSyncCallbacks @ react-dom.development.js:11982
flushSync @ react-dom.development.js:26040
legacyCreateRootFromDOMContainer @ react-dom.development.js:29309
legacyRenderSubtreeIntoContainer @ react-dom.development.js:29335
render @ react-dom.development.js:29419
./src/index.js @ index.js:7
options.factory @ react refresh:6
__webpack_require__ @ bootstrap:24
(anonymous) @ startup:7
(anonymous) @ startup:7
App.js:18 Uncaught TypeError: Cannot read properties of null (reading 'map')
    at App (App.js:18:1)
    at renderWithHooks (react-dom.development.js:16141:1)
    at mountIndeterminateComponent (react-dom.development.js:20838:1)
    at beginWork (react-dom.development.js:22342:1)
    at beginWork$1 (react-dom.development.js:27219:1)
    at performUnitOfWork (react-dom.development.js:26392:1)
    at workLoopSync (react-dom.development.js:26303:1)
    at renderRootSync (react-dom.development.js:26271:1)
    at performSyncWorkOnRoot (react-dom.development.js:25924:1)
    at flushSyncCallbacks (react-dom.development.js:11982:1)
App @ App.js:18
renderWithHooks @ react-dom.development.js:16141
mountIndeterminateComponent @ react-dom.development.js:20838
beginWork @ react-dom.development.js:22342
beginWork$1 @ react-dom.development.js:27219
performUnitOfWork @ react-dom.development.js:26392
workLoopSync @ react-dom.development.js:26303
renderRootSync @ react-dom.development.js:26271
performSyncWorkOnRoot @ react-dom.development.js:25924
flushSyncCallbacks @ react-dom.development.js:11982
flushSync @ react-dom.development.js:26040
legacyCreateRootFromDOMContainer @ react-dom.development.js:29309
legacyRenderSubtreeIntoContainer @ react-dom.development.js:29335
render @ react-dom.development.js:29419
./src/index.js @ index.js:7
options.factory @ react refresh:6
__webpack_require__ @ bootstrap:24
(anonymous) @ startup:7
(anonymous) @ startup:7

順便說一句,產品組件看起來像:

const Product = ({ name, img, description, price }) => {
  return (
    <div className="product">
      <h2>{name}</h2>
      <img src={`/img/${img}`} alt={description} />
      <p>{description}</p>
      <p>{price}</p>
    </div>
  );
};

export default Product;

那么這里發生了什么? 為什么沒有在瀏覽器中呈現?

您將products的初始值設置為null

 const [products, setProducts] = useState(null);

然后您嘗試在其上調用 map:

 {products.map((product) => (

此時,它不是數組,也沒有map方法。

因此應用程序崩潰(在渲染結束時運行會調用fetch的效果掛鈎之前)。

您需要:

  • 處理它是null的情況(例如通過測試它並返回加載指示器)
  • 將其初始化為一個空數組而不是null

同樣在瀏覽器控制台中,有很多警報消息

它們與您的問題無關……但在錯誤消息本身和它們鏈接到的文檔中也有非常清楚的解釋。

暫無
暫無

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

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