数据未进入产品详情页面。返回一个空数组
2022-07-31
60
当我单击任何项​​目时,产品详细信息页面中都会显示一个空数组。第一次单击其中一个产品时,它会显示此产品 ID 上的所有内容,但一段时间后,它显示一个空数组。并显示此错误 ProductDetails.jsx:56 Uncaught TypeError:无法读取未定义的属性(读取“图像”)。我在这里使用 reactjs 18 版本、redux-toolkit 和 node 16 版本。请帮我解决这个问题。
-----------------PeoductDetails.jsx ----------------------
import React, { useEffect, useState } from 'react'
import { useDispatch, useSelector } from 'react-redux';
import MetaData from '../../more/MetaData'
import { getSingleProduct, STATUSES } from '../../store/slices/productSlice';
import Header from '../Home/Header'
import { useParams } from "react-router-dom";
import loading from "../../assets/loading.svg"
import Slider from "react-slick";
import FavoriteBorderIcon from '@mui/icons-material/FavoriteBorder';
import ShoppingBagOutlinedIcon from '@mui/icons-material/ShoppingBagOutlined';
const ProductDetails = () => {
const dispatch = useDispatch();
const { id } = useParams()
const { products, status } = useSelector((state) => state.product)
console.log(products);
const slider = {
dots: true,
infinite: true,
slidesToShow: 1,
slidesToScroll: 1,
autoplay: true,
speed: 3000,
autoplaySpeed: 6000,
cssEase: "linear"
};
useEffect(() => {
const fetchProduct = () => {
const action = getSingleProduct(id?.toString())
dispatch(action)
}
fetchProduct()
}, [dispatch, id])
console.log(products.product);
if (status === STATUSES.LOADING) {
return (
<div className="w-full h-[100vh] flex justify-center items-center bg-
gray-100">
<img src={loading} alt="" className="bg-transparent rounded-full h-
[300px]" />
</div>
);
}
return (
<>
<MetaData title="Product Details" />
<Header />
<div className="w-full flex justify-around md:flex-row flex-col">
<div>
<Slider {...slider}>
<div>
{products.product.images &&
products.product.images.map((item, i) => (
<img
key={i}
src={item.url}
alt={`${i} Slide`}
className="w-[350px] h-[350px] object-contain"
/>
))}
</div>
</Slider>
</div>
<div>
<h2>{products.product.name}</h2>
<div>
<span>({products.product.numOfReviews})</span>
</div>
<h2>₹{products.product.price}</h2>
<div>
<sapn>Quantity</sapn>
<div>
<button>-</button>
<input type="number" />
<button>+</button>
</div>
</div>
<p>{products.product.stock < 1 ? "OutOfStock" : "InStock"}</p>
<div>
{products.product.description}
</div>
<div>
<div>
<FavoriteBorderIcon />
<span>Add to wishlist</span>
</div>
<div>
<ShoppingBagOutlinedIcon />
<span>Add to Cart</span>
</div>
</div>
</div>
</div>
</>
)
}
export default ProductDetails
---------- productSlice.js -------------------------------------
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import * as api from "../api";
export const STATUSES = Object.freeze({
IDLE: 'idle',
ERROR: 'error',
LOADING: 'loading',
});
// Thunk
export const fetchAllProducts = createAsyncThunk("products/getAllProduct", async (_,
thunkAPI) => {
try {
const response = await api.getAllProducts()
return response.data
}catch(error){
return thunkAPI.rejectWithValue(error.response.data)
}
})
export const getSingleProduct = createAsyncThunk("product/getSingleProduct", async
(id, { rejectWithValue }) => {
try {
const response = await api.getSingleProduct(id)
console.log(response.data);
return await response.data
}catch(error){
console.log(error.response)
return rejectWithValue(error.response)
}
})
const productSlice = createSlice({
name: "product",
initialState: {
products: [],
status: STATUSES.IDLE,
message: ""
},
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchAllProducts.pending, (state, action) => {
state.status = STATUSES.LOADING
})
.addCase(fetchAllProducts.fulfilled, (state, action) => {
state.products = action.payload
state.status = STATUSES.IDLE
})
.addCase(fetchAllProducts.rejected, (state, action) => {
state.status = STATUSES.ERROR
state.message = action.payload.message
})
.addCase(getSingleProduct.pending, (state, action) => {
state.status = STATUSES.LOADING
})
.addCase(getSingleProduct.fulfilled, (state, action) => {
state.products = action.payload
state.status = STATUSES.IDLE
})
.addCase(getSingleProduct.rejected, (state, action) => {
state.status = STATUSES.ERROR
state.message = action.payload.message
})
}
})
export default productSlice.reducer
----------------------- store.js ----------------------
import { configureStore } from "@reduxjs/toolkit";
import productSlice from "./slices/productSlice";
const store = configureStore({
reducer: {
product: productSlice
}
})
导出默认商店
------- api.js ----------------
import axios from 'axios';
const API = axios.create({
baseURL: "http://localhost:5000",
headers: {
'Content-Type': 'application/json',
},
})
export const getAllProducts = async () => await API.get("/api/v2/products")
export const getSingleProduct = async (id) => await API.get(`/api/v2/products/${id}`)
------- 错误 ---
ProductDetails.jsx:56 Uncaught TypeError: Cannot read properties of undefined
(reading 'images')
at ProductDetails (ProductDetails.jsx:56:1)
at renderWithHooks (react-dom.development.js:16305:1)
at mountIndeterminateComponent (react-dom.development.js:20074:1)
at beginWork (react-dom.development.js:21587:1)
at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1)
at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1)
at invokeGuardedCallback (react-dom.development.js:4277:1)
at beginWork$1 (react-dom.development.js:27451:1)
at performUnitOfWork (react-dom.development.js:26557:1)
at workLoopSync (react-dom.development.js:26466:1)
2个回答
看起来产品数组是空的,您需要为单个产品创建不同的状态切片,如
currentProduct
。请记住,空数组返回
true
,因此产品将返回 true,因此访问空数组上的任何属性都会出错。您可以通过
products.length > 0
或
lodash
中的
_.isEmpty()
检查数组是否为空。>
Aman
2022-07-31
在 ProductDetails.jsx
useEffect(() => {
const fetchProduct = () => {
//const action = getSingleProduct(id?.toString()) // remove
const action = getSingleProduct(id) // use
dispatch(action)
}
fetchProduct()
}, [dispatch, id])
Pavitar Sharma
2022-07-31