javascript - 在 React 应用程序中找不到错误
问题描述
我一直在用 React 编写一个应用程序(电子商务,作为一个项目,遵循一个教程)。引用购物车对象时,我收到“TypeError:无法读取未定义的属性“长度””的错误。这是一些背景背景。我正在使用 App.js 组件顶部附近的 useState 挂钩生成购物车对象:
const [cart, setCart] = useState({});
在 App.js 再往下一点,console.log 语句执行时没有错误提示购物车对象存在:
console.log(cart);
但是,当我尝试将购物车对象传递给 App.js 渲染部分中的购物车组件时,会生成上述错误(例如“TypeError:无法读取未定义的属性“长度”)。为什么会发生这种情况,我该如何解决?
这是 App.js 的代码
import React, { useState, useEffect } from 'react'
import { commerce } from './lib/commerce';
import { Products, Navbar, Cart } from './components';
const App = () => {
const [products, setProducts] = useState([]);
const [cart, setCart] = useState({});
const fetchProducts = async () => {
const { data } = await commerce.products.list();
setProducts(data);
}
const fetchCart = async () => {
setCart(await commerce.cart.retrieve());
}
const handleAddToCart = async (productID, quantity) => {
const item = await commerce.cart.add(productID, quantity);
setCart(item.cart);
}
useEffect(() => {
fetchProducts();
fetchCart();
}, []);
console.log(cart);
return (
<div>
<Navbar totalItems={cart.total_items} />
{/* <Products products={products} onAddToCart={handleAddToCart} /> */}
<Cart cart={cart} />
</div>
)
}
export default App
这是我将购物车对象传递到的组件(购物车)的代码:
import React from 'react'
import { Container, Typography, Button, Grid } from "@material-ui/core";
import useStyles from './styles';
const Cart = ({ cart }) => {
const isEmpty = !cart.line_items.length;
const classes = useStyles();
const EmptyCart = () => {
<Typography variant="subtitle1">
You have no items your shopping cart..
</Typography>
}
const FilledCart = () => {
<>
<Grid container spacing={3}>
{
cart.line_items.map((item) => (
<Grid item xs={12} sm={4} key={item.id}>
<div>{item.name}</div>
</Grid>
))
}
</Grid>
<div className={classes.cardDetails}>
<Typography variant="h4">
Subtotal: { cart.subtotal.formatted_with_symbol }
</Typography>
<div>
<Button className={classes.emptyButton} size="large" variant="contained" type="button" color="secondary">Empty Cart</Button>
<Button className={classes.checkoutButton} size="large" variant="contained" type="button" color="primary">Checkout</Button>
</div>
</div>
</>
}
return (
<Container>
<div className={classes.toolbar} />
<Typography className={classes.title} variant="h3">Your shopping cart</Typography>
{
isEmpty ? <EmptyCart /> : <FilledCart />
}
</Container>
)
}
export default Cart
解决方案
问题
您的代码的问题是初始状态与您在初始渲染中访问的内容不匹配。
在
App
组件中,cart
状态只是一个空对象。const [cart, setCart] = useState({});
cart
作为 props 传递给Cart
组件,并且代码假定cart.line_items
是为了访问length
属性或map
函数而定义的。cart.line_items
OFC 未定义,因此尝试访问该length
属性 (或map
) 会抛出TypeError: Cannot read property 'XYZ' of undefined
const isEmpty = !cart.line_items.length;
和
cart.line_items.map(.....
但是当我在 App.js 中 console.log 时,它实际上会打印出必要的信息。
它console.log(cart);
位于组件的函数体中,因此它错误地将cart
状态记录为无意的副作用,应该从useEffect
挂钩中记录它,以便您查看每个渲染周期的值。这里的另一个问题是您没有访问任何嵌套属性,因此这永远不会引发错误。我敢打赌,使用此代码,您至少有 1 或 2 个日志条目,它们只是空对象 ( {}
) ,然后您会看到一些具有填充嵌套属性的日志。
可能的日志输出示例:
{} {} { line_items: [.....], subtotal: ..... } { line_items: [.....], subtotal: ..... }
解决方案
关于状态记录,您应该使用useEffect
依赖于您正在记录的状态值的挂钩。这将cart
在初始渲染时记录状态,稍后仅在cart
更新状态值时记录。
useEffect(() => {
console.log(cart);
}, [cart]);
对于错误,您有几个选项可以帮助防止在访问您的cart
状态时出现错误。
提供与渲染周期中访问的内容相匹配的有效初始状态,添加
line_items: []
到初始cart
状态,使其cart.line_items
现在存在并具有length
属性。const [cart, setCart] = useState({ line_items: [] });
cart
在传递的道具上使用保护子句或可选链接。const isEmpty = !(cart.line_items && cart.line_items.length);
或者
const isEmpty = !cart.line_items?.length);
和
cart.line_items && cart.line_items.map(.....
或者
cart.line_items?.map(.....
cart.subtotal
在未定义的情况下也可以保护小计子状态。<Typography variant="h4"> Subtotal: { cart.subtotal?.formatted_with_symbol } </Typography>
推荐阅读
- powershell - 通过 PowerShell 部署时,如何将共享数据源绑定到共享数据集?
- javascript - Firebase .OrderByChild() 不适用于布尔值
- database - 在VBA(Access)中独立地重新查询表单的多个实例
- c - 我应该在中断程序中检索 SPI 数据吗?
- python - 声明性基础不收集表格
- listview - ExpansionTile 内的 ListView 不起作用
- go - sync.Waitgroup 不会阻止执行
- python - 正则表达式仅匹配用逗号分隔的唯一名称
- javascript - Jquery Smooth Scrolling 跳转而不是滚动 - 我该如何解决?
- wordpress - 如何在我的商店页面(列出所有产品的页面)上缩小我的特征图像的大小(不是文件大小)?