未捕获的类型错误:无法读取未定义的属性(读取‘源’)
2021-09-21
14458
我尝试从 commerceJS API 访问从不同模块获取并作为 prop 传递的数据,只有当我调用嵌套产品对象时,代码才会中断,并出现此错误
Uncaught TypeError: Cannot read properties of undefined (reading 'source')
。
我在店面上使用了相同的 API,
{product.media.source
运行正常。我正在尝试制作一个预览模块,当我调用嵌套对象时,它会中断。
请帮忙。
这是我的代码
const Preview = ({ products, onAddToCart }) => {
const [product, setProduct] = useState({});
const params = useParams();
const findProduct = (id) => {
return products.find((product) => {
setProduct(product);
return product.id === id;
});
};
const productId = params.id;
useEffect(() => {
findProduct(productId);
});
return (
<Card sx={{ maxWidth: 345 }} style={{ marginTop: '90px' }}>
<CardMedia image={product.media.source} title={product.name}></CardMedia>
<CardContent>
<Typography gutterBottom variant='h5' component='div'>
{product.name}
</Typography>
<Typography
variant='body2'
color='textSecondary'
dangerouslySetInnerHTML={{ __html: product.description }}
></Typography>
</CardContent>
<CardActions>
<IconButton component={Link} variant='outlined' to='/'>
Go Back
</IconButton>
<IconButton aria-label='Add to Cart' onClick={() => onAddToCart(product.id, 1)}>
<AddShoppingCart />
</IconButton>
</CardActions>
</Card>
);
这是产品对象 产品对象
2个回答
显然,您的
product
对象默认不包含
media
字段。您需要等到它可用后才能使用它。
尝试以下方法:
const Preview = ({ products, onAddToCart }) => {
const [product, setProduct] = useState();
const params = useParams();
console.log(products[0]);
console.log(params.id);
const findProduct = useCallback((id) => {
return products.find((product) => {
if (product.id === id) { // <-- render optimization
setProduct(product);
return true;
}
return false;
});
}, [products]);
const productId = useMemo(() => params.id, [params.id]);
useEffect(() => {
findProduct(productId);
}, [productId, findProduct]);
const renderCard = useCallback(() => {
if (!product) return null; // <-- here you can implement your placeholder component
return (
<Card sx={{ maxWidth: 345 }} style={{ marginTop: '90px' }}>
<CardMedia image={product.media.source} title={product.name}/>
<CardContent>
<Typography gutterBottom variant='h5' component='div'>
{product.name}
</Typography>
<Typography
variant='body2'
color='textSecondary'
dangerouslySetInnerHTML={{ __html: product.description }}
></Typography>
</CardContent>
<CardActions>
<IconButton component={Link} variant='outlined' to='/'>
Go Back
</IconButton>
<IconButton aria-label='Add to Cart' onClick={() => onAddToCart(product.id, 1)}>
<AddShoppingCart />
</IconButton>
</CardActions>
</Card>
);
}, [product]);
return renderCard();
};
或者像这样:
const initialState = { // <-- you need to change this as you need
active: true,
assets: [/* ... */],
categories: [/* ... */],
checkout_url: {
checkout: 'placeholder://checkout.url',
display: 'placeholder://display.url',
/* ... */
},
collects: {/*...*/}
created: 0,
description: 'placeholder description',
extra_fields: [/* ... */],
hsa: {/* ... */},
id: 'placeholder_id',
invenotry: {/* ... */},
is: {/* ... */},
media: {
type: 'image',
source: 'placeholder://image.source',
/* ... */
},
meta: null,
/* ... */
};
const Preview = ({ products, onAddToCart }) => {
const [product, setProduct] = useState(initialState);
const params = useParams();
console.log(products[0]);
console.log(params.id);
const findProduct = useCallback((id) => {
return products.find((product) => {
if (product.id === id) { // <-- render optimization
setProduct(product);
return true;
}
return false;
});
}, [products]);
const productId = useMemo(() => params.id, [params.id]);
useEffect(() => {
findProduct(productId);
}, [productId, findProduct]);
return (
<Card sx={{ maxWidth: 345 }} style={{ marginTop: '90px' }}>
<CardMedia image={product.media.source} title={product.name}/>
<CardContent>
<Typography gutterBottom variant='h5' component='div'>
{product.name}
</Typography>
<Typography
variant='body2'
color='textSecondary'
dangerouslySetInnerHTML={{ __html: product.description }}
></Typography>
</CardContent>
<CardActions>
<IconButton component={Link} variant='outlined' to='/'>
Go Back
</IconButton>
<IconButton aria-label='Add to Cart' onClick={() => onAddToCart(product.id, 1)}>
<AddShoppingCart />
</IconButton>
</CardActions>
</Card>
);
};
wowandy
2021-09-21
根据上面的代码
console.log(products[0]);
console.log(params.id);
const findProduct = (id) => {
return products.find((product) => {
setProduct(product);
return product.id === id;
});
};
看起来产品是一个数组而不是一个对象。我认为这是您可能错过的地方。
因此,
product.media.source
会抛出错误,因为 product.media 未定义。
请检查您可能要添加的产品。
Omkar
2021-09-21