"TypeError: Cannot destructure property 'product' of 'productDetails' as it is undefined"
"TypeError: Cannot destructure property 'product' of 'productDetails' as it is undefined"
我目前正在尝试在产品屏幕上显示产品数据。这是我在打开产品详细信息屏幕时在控制台中遇到的错误。
TypeError: Cannot destructure property 'product' of 'productDetails' as it is undefined.
我不确定为什么未定义 productDetails。它应该包含产品详细信息数据。
这是我的代码。
ProductScreen.js
import React, { useEffect } from 'react';
import { useParams } from "react-router-dom";
import {Link} from "react-router-dom";
import { useSelector, useDispatch } from 'react-redux';
import { detailsProduct } from "../actions/productActions"
function ProductScreen() {
const { id } = useParams();
const productDetails = useSelector(state => state.productDetails);
const {product, loading, error} = productDetails;
const dispatch = useDispatch;
console.log("something");
useEffect(() => {
dispatch(detailsProduct(id));
return () => {
//
};
}, []);
return <div>
<div className="back-to-results">
<Link to="/">Back to results</Link>
</div>
{loading ? <div>Loading...</div> :
error ? <div>{error}</div> :
(
<div className="details">
<div className="details-image">
<img src={product.image} alt="product" ></img>
</div>
<div className="details-info">
<ul>
<li>
<h4>{product.name}</h4>
</li>
<li>
{product.rating} Stars ({product.numReviews} Reviews)
</li>
<li>
{product.price}
</li>
<li>
Description:
<div>
{product.description}
</div>
</li>
</ul>
</div>
<div className="details-action">
<ul>
<li>
Price: <b>${product.price}</b>
</li>
<li>
Status: {product.status}
</li>
<li>
Qty: <select>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
</li>
<li>
<button className="button">Add to Cart</button>
</li>
</ul>
</div>
</div>
)
}
</div>
}
export default ProductScreen;
productActions.js
import { PRODUCT_LIST_FAIL, PRODUCT_LIST_REQUEST, PRODUCT_LIST_SUCCESS, PRODUCT_DETAILS_REQUEST, PRODUCT_DETAILS_SUCCESS, PRODUCT_DETAILS_FAIL } from "../constants/productconstants.js";
import axios from "axios";
const listProducts = () => async (dispatch) => {
try {
dispatch({type: PRODUCT_LIST_REQUEST});
const {data} = await axios.get("/api/products");
dispatch({type: PRODUCT_LIST_SUCCESS, payload: data});
}
catch (error) {
dispatch({type: PRODUCT_LIST_FAIL, payload:error.message});
}
}
const detailsProduct = (productId) => async (dispatch) => {
try {
dispatch({type: PRODUCT_DETAILS_REQUEST, payload: productId});
const {data} = await axios.get("/api/products/" + productId);
dispatch({type: PRODUCT_DETAILS_SUCCESS, payload: data});
}
catch (error) {
dispatch({type: PRODUCT_DETAILS_FAIL, payload: error.message});
}
}
export {listProducts, detailsProduct};
最初当页面呈现时,productDetails 状态应该为空或未定义,尽管您已经在 useEffect 中发送了 detailsProduct,但是从 API 请求获取数据需要一些时间,这就是您收到错误的原因。您可以在不解构的情况下使用 productDetails
productDetails?.loading
productDetails?.product?.name
productDetails 和 loading 之间的问号是 Optional Chaining 你可以阅读更多:
Optional Chaining
**
已更新
**
function ProductScreen() {
const { id } = useParams();
const productDetails = useSelector((state) => state.productDetails);
const data = productDetails;
const dispatch = useDispatch();
console.log("something", data);
useEffect(() => {
dispatch(detailsProduct(id));
return () => {
//
};
}, []);
useEffect(() => {
console.log(productDetails)
}, [productDetails]);
return (
<div>
<div className="back-to-results">
<Link to="/">Back to results</Link>
</div>
{data?.loading ? (
<div>Loading...</div>
) : data?.error ? (
<div>{data?.error}</div>
) : (
<div className="details">
<div className="details-image">
<img src={data?.product?.image} alt="product"></img>
</div>
<div className="details-info">
<ul>
<li>
<h4>{data?.product?.name}</h4>
</li>
<li>
{data?.product?.rating} Stars
{data?.product?.numReviews} Reviews
</li>
<li>{data?.product?.price}</li>
<li>
Description:
<div>{data?.product?.description}</div>
</li>
</ul>
</div>
<div className="details-action">
<ul>
<li>
Price: <b>${data?.product?.price}</b>
</li>
<li>Status: {data?.product?.status}</li>
<li>
Qty:{" "}
<select>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
</li>
<li>
<button className="button">Add to Cart</button>
</li>
</ul>
</div>
</div>
)}
</div>
);
}
export default ProductScreen;
我目前正在尝试在产品屏幕上显示产品数据。这是我在打开产品详细信息屏幕时在控制台中遇到的错误。
TypeError: Cannot destructure property 'product' of 'productDetails' as it is undefined.
我不确定为什么未定义 productDetails。它应该包含产品详细信息数据。
这是我的代码。
ProductScreen.js
import React, { useEffect } from 'react';
import { useParams } from "react-router-dom";
import {Link} from "react-router-dom";
import { useSelector, useDispatch } from 'react-redux';
import { detailsProduct } from "../actions/productActions"
function ProductScreen() {
const { id } = useParams();
const productDetails = useSelector(state => state.productDetails);
const {product, loading, error} = productDetails;
const dispatch = useDispatch;
console.log("something");
useEffect(() => {
dispatch(detailsProduct(id));
return () => {
//
};
}, []);
return <div>
<div className="back-to-results">
<Link to="/">Back to results</Link>
</div>
{loading ? <div>Loading...</div> :
error ? <div>{error}</div> :
(
<div className="details">
<div className="details-image">
<img src={product.image} alt="product" ></img>
</div>
<div className="details-info">
<ul>
<li>
<h4>{product.name}</h4>
</li>
<li>
{product.rating} Stars ({product.numReviews} Reviews)
</li>
<li>
{product.price}
</li>
<li>
Description:
<div>
{product.description}
</div>
</li>
</ul>
</div>
<div className="details-action">
<ul>
<li>
Price: <b>${product.price}</b>
</li>
<li>
Status: {product.status}
</li>
<li>
Qty: <select>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
</li>
<li>
<button className="button">Add to Cart</button>
</li>
</ul>
</div>
</div>
)
}
</div>
}
export default ProductScreen;
productActions.js
import { PRODUCT_LIST_FAIL, PRODUCT_LIST_REQUEST, PRODUCT_LIST_SUCCESS, PRODUCT_DETAILS_REQUEST, PRODUCT_DETAILS_SUCCESS, PRODUCT_DETAILS_FAIL } from "../constants/productconstants.js";
import axios from "axios";
const listProducts = () => async (dispatch) => {
try {
dispatch({type: PRODUCT_LIST_REQUEST});
const {data} = await axios.get("/api/products");
dispatch({type: PRODUCT_LIST_SUCCESS, payload: data});
}
catch (error) {
dispatch({type: PRODUCT_LIST_FAIL, payload:error.message});
}
}
const detailsProduct = (productId) => async (dispatch) => {
try {
dispatch({type: PRODUCT_DETAILS_REQUEST, payload: productId});
const {data} = await axios.get("/api/products/" + productId);
dispatch({type: PRODUCT_DETAILS_SUCCESS, payload: data});
}
catch (error) {
dispatch({type: PRODUCT_DETAILS_FAIL, payload: error.message});
}
}
export {listProducts, detailsProduct};
最初当页面呈现时,productDetails 状态应该为空或未定义,尽管您已经在 useEffect 中发送了 detailsProduct,但是从 API 请求获取数据需要一些时间,这就是您收到错误的原因。您可以在不解构的情况下使用 productDetails
productDetails?.loading
productDetails?.product?.name
productDetails 和 loading 之间的问号是 Optional Chaining 你可以阅读更多: Optional Chaining
**
已更新
**
function ProductScreen() {
const { id } = useParams();
const productDetails = useSelector((state) => state.productDetails);
const data = productDetails;
const dispatch = useDispatch();
console.log("something", data);
useEffect(() => {
dispatch(detailsProduct(id));
return () => {
//
};
}, []);
useEffect(() => {
console.log(productDetails)
}, [productDetails]);
return (
<div>
<div className="back-to-results">
<Link to="/">Back to results</Link>
</div>
{data?.loading ? (
<div>Loading...</div>
) : data?.error ? (
<div>{data?.error}</div>
) : (
<div className="details">
<div className="details-image">
<img src={data?.product?.image} alt="product"></img>
</div>
<div className="details-info">
<ul>
<li>
<h4>{data?.product?.name}</h4>
</li>
<li>
{data?.product?.rating} Stars
{data?.product?.numReviews} Reviews
</li>
<li>{data?.product?.price}</li>
<li>
Description:
<div>{data?.product?.description}</div>
</li>
</ul>
</div>
<div className="details-action">
<ul>
<li>
Price: <b>${data?.product?.price}</b>
</li>
<li>Status: {data?.product?.status}</li>
<li>
Qty:{" "}
<select>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
</li>
<li>
<button className="button">Add to Cart</button>
</li>
</ul>
</div>
</div>
)}
</div>
);
}
export default ProductScreen;