我目前正在构建具有“添加到购物车”功能的电子商务网站,我在“购物车”类中工作。我正在使用Redux - onDelete函数用于存在“删除”按钮的情况,并且可以通过单击(调用onClick)将其从当前购物车状态中移除。
这是我一直在尝试的方法,但是它不起作用并抛出错误:“ TypeError:无法读取未定义的属性'onClick'”。
您可以看到我已经将 this 传递给了构造函数中的onClick函数,因此在Button的onClick属性中,我只是将cartID传递给了onClick函数:
Cart.js文件
class Cart extends React.Component {
constructor() {
super();
this.onClick = this.onDelete.bind(this);
}
onDelete(_id) {
//
}
render() {
// if more than 1 item in cart array, then render the cart
// otherwise, render empty
if(this.props.cart[0]) {
return this.renderCart();
} else {
return this.renderEmpty();
}
}
renderEmpty() {
return (<div>Empty Cart</div>)
}
renderCart() {
const cartItemsList = this.props.cart.map(function(cartArr) {
return (
<Card key={cartArr._id}>
<Row>
<Col>
<h6>{cartArr.title}</h6>
</Col>
<Col>
<h6>USD {cartArr.price}</h6>
</Col>
<Col>
<h6>qty. goes here</h6>
</Col>
<Col>
<ButtonGroup style={{minWidth:'300px'}}>
<Button
variant = "default"
size = "small">
-
</Button>
<Button
variant = "default"
size = "small">
+
</Button>
<span> </span>
<Button
onClick = {this.onClick(cartArr._id)}
variant = "danger"
size = "small">
DELETE
</Button>
</ButtonGroup>
</Col>
</Row>
</Card>
)
})
return (
<Card>
{cartItemsList}
</Card>
)
}
}
我知道部分原因是我传递给onClick函数的this关键字的性质。当我按照教程进行并在cartItemList的末尾添加this关键字时,效果很好:
class Cart extends React.Component {
constructor() {
super();
this.onClick = this.onDelete.bind(this);
}
onDelete(_id) {
//
}
render() {
// if more than 1 item in cart array, then render the cart
// otherwise, render empty
if(this.props.cart[0]) {
return this.renderCart();
} else {
return this.renderEmpty();
}
}
renderEmpty() {
return (<div>Empty Cart</div>)
}
renderCart() {
const cartItemsList = this.props.cart.map(function(cartArr) {
return (
<Card key={cartArr._id}>
<Row>
<Col>
<h6>{cartArr.title}</h6>
</Col>
<Col>
<h6>USD {cartArr.price}</h6>
</Col>
<Col>
<h6>qty. goes here</h6>
</Col>
<Col>
<ButtonGroup style={{minWidth:'300px'}}>
<Button
variant = "default"
size = "small">
-
</Button>
<Button
variant = "default"
size = "small">
+
</Button>
<span> </span>
<Button
onClick = {this.onClick(cartArr._id)}
variant = "danger"
size = "small">
DELETE
</Button>
</ButtonGroup>
</Col>
</Row>
</Card>
)
})
return (
<Card>
{cartItemsList}
</Card>
)
}
}
答案 0 :(得分:3)
onClick = {this.onClick(cartArr._id)}
将此行更改为
onClick = {() => this.onClick(cartArr._id)}
答案 1 :(得分:2)
使用您的语法
onClick = {this.onClick(cartArr._id)}
该函数被立即调用,而不是单击。
您需要
onClick = {() => this.onClick(cartArr._id)}
相反。
无论如何,现代ES无需手动绑定东西;改用箭头功能。
这是我编写组件的方式(如果它必须是类组件,而不是功能组件):
class Cart extends React.Component {
// Arrow functions are automagically bound
onDelete = (_id) => {
const { cart } = this.props;
const cartWithoutGivenId = cart.filter((item) => item._id !== _id);
const cartAfterDelete = { books: cartWithoutGivenId };
this.props.deleteFromCart(cartAfterDelete);
};
render() {
const { cart } = this.props;
if (!cart.length) {
return <div>Empty Cart</div>;
}
const cartItemsList = cart.map((item) => (
<Card key={item._id}>
<Row>
<Col>
<h6>{item.title}</h6>
</Col>
<Col>
<h6>USD {item.price}</h6>
</Col>
<Col>
<h6>qty. goes here</h6>
</Col>
<Col>
<ButtonGroup style={{ minWidth: "300px" }}>
<Button variant="default" size="small">
-
</Button>
<Button variant="default" size="small">
+
</Button>
<Button
onClick={() => this.onDelete(item._id)}
variant="danger"
size="small"
>
DELETE
</Button>
</ButtonGroup>
</Col>
</Row>
</Card>
));
return <Card>{cartItemsList}</Card>;
}
}
为完整起见,这里有一对功能组件:
const CartItem = ({ item, onDelete }) => (
<Card>
<Row>
<Col>
<h6>{item.title}</h6>
</Col>
<Col>
<h6>USD {item.price}</h6>
</Col>
<Col>
<h6>qty. goes here</h6>
</Col>
<Col>
<ButtonGroup style={{ minWidth: "300px" }}>
<Button variant="default" size="small">
-
</Button>
<Button variant="default" size="small">
+
</Button>
<Button
onClick={() => onDelete(item._id)}
variant="danger"
size="small"
>
DELETE
</Button>
</ButtonGroup>
</Col>
</Row>
</Card>
);
const Cart = ({ cart, deleteFromCart }) => {
const onDelete = React.useCallback(
(_id) => {
const cartWithoutGivenId = cart.filter((item) => item._id !== _id);
const cartAfterDelete = { books: cartWithoutGivenId };
deleteFromCart(cartAfterDelete);
},
[cart],
);
if (!cart.length) {
return <div>Empty Cart</div>;
}
return (
<Card>
{cart.map((item) => (
<CartItem key={item._id} item={item} onDelete={onDelete} />
))}
</Card>
);
};
答案 2 :(得分:1)
您应该使用currying。
当您编写this.onClick(cartArr._id)
时,它的值将为undefined,但希望获得一个回调函数。因此,您需要从onDelete返回一个函数,如下所示:
onDelete(id) {
return function() {
//On delete logic
}
}
通过这种方式,您可以避免通过使用类属性和箭头函数(https://medium.com/quick-code/react-quick-tip-use-class-properties-and-arrow-functions-to-avoid-binding-this-to-methods-29628aca2e25)来绑定回调
希望如此,祝您好运!
答案 3 :(得分:1)
除了其他答案外,我还要添加解释为什么,您的代码会引发df.rename(columns={"1999q4": "Quarter", 9926.1: "GDP"}, inplace = True)
错误。
您根据map
docs将"TypeError: Cannot read property 'onClick' of undefined".
回调定义为常规函数(不是箭头函数):
如果提供了thisArg参数,它将用作回调的this 值。否则,将使用undefined值作为此值。
因此map
回调中的this
是map
,这就是为什么会出错的原因。尽管undefined
函数已正确地“绑定”,但您无法访问此函数,因为onClick
回调中的this
并不指向组件实例。要解决此问题,您可以将箭头函数用作map
回调而不是常规函数(因为使用了封闭词法作用域的箭头函数map
内部)。