使用某些方法时,我需要更新我的redux存储。我可以在挂载并调用updateCartList()
时在组件中渲染虚拟数据,但是当我尝试使用componentDidUpdate()
进行更新并调用updateCartInfo()
来更新购物车时,会得到一个错误Cannot read property 'id' of undefined
已编辑:添加了完整的组件和操作
这是伪数据dataList
export const dataList = [
{
id: '1',
image: '/rice.jpg',
price: 32,
product: 'Yellow Corn',
quantity: 2,
},
{
id: '2',
image: '/rice.jpg',
price: 400,
product: 'Beans',
quantity: 5,
},
{
id: '3',
image: '/rice.jpg',
price: 32,
product: 'Banana',
quantity: 1,
},
];
成分减少剂
const initialState = {
cart: new Map(),
};
/**
* Creates a Javascript Map with the cart's items mapped by id
*
* @param {Array} cartData - a cart item
* @return {Map} - the new cart data list
*/
function generateCartsMap(dataList) {
const cartData = new Map();
dataList.forEach(list => {
const { id } = list;
cartData.set(id, list);
});
return cartData;
}
/**
* Updates the data in the cart list
*
* @param {Object} cartItem - the cart item to be updated
* @param {Map} list - the list of producer products
* @return {Map} - the updated dataSource
*/
function updateCartInfo(cartItem, list) {
const { id } = cartItem;
const newList = new Map([...list.entries()]);
newList.set(id, cartItem);
return newList;
}
export default (state = { ...initialState }, action) => {
switch (action.type) {
case UPDATE_CART_LIST: {
const { payload } = action;
return {
...state,
cart: generateCartsMap(payload),
};
}
case UPDATE_CART_INFO: {
const { payload } = action;
const { cart } = state;
return {
...state,
cart: updateCartInfo(payload, cart),
};
}
default:
return state;
}
};
内部应用程序的状态和方法
class Cart extends Component {
state = {
dataList: dataList,
};
componentDidMount() {
const { updateCartList } = this.props.actions;
const { dataList } = this.state;
updateCartList(dataList);
}
componentDidUpdate(prevProp) {
const { cart: newList } = this.props;
const { cart: oldList } = prevProp;
if (newList != oldList) {
const { updateCartInfo } = this.props.actions;
updateCartInfo();
}
}
handleRemove = item => {
const { cart } = this.props;
const defaultCart = [...cart.values()];
const newCart = defaultCart.filter(({ id }) => id !== item.id);
this.setState({
dataList: newCart,
});
};
handleQuantityChange = (row, action) => {
const { cart } = this.props;
const values = [...cart.values()];
const index = values.findIndex(item => row.id === item.id);
if (action === 'add') {
values[index] = {
...values[index],
quantity: values[index].quantity + 1,
};
} else {
values[index] = {
...values[index],
quantity:
values[index].quantity > 1
? values[index].quantity - 1
: values[index].quantity,
};
}
this.setState({
dataList: values,
});
};
handleClearCart = () => {
const cart = [];
this.setState({
dataList: cart,
});
};
render() {
const { cart } = this.props;
const values = [...cart.values()];
return (
<div className="cart-page">
<div className="cart-top">
<h2 className="cart-heading">
{`Cart`}
<Badge
count={values.length}
// title={}
style={{ backgroundColor: '#001529' }}
/>
</h2>
<Popconfirm
className="cart-clear"
title="Are you sure you want to remove item?"
onConfirm={() => this.handleClearCart()}
>
<Button type="danger">{'Clear Cart'}</Button>
</Popconfirm>
</div>
<div className="cart-top">
<AppLink key={MARKET} to={MARKET}>
<Button className="cart-heading">{`Continue Shopping`}</Button>
</AppLink>
<AppLink key={'checkout'} to={'./'}>
<Button className="cart-checkout">{'Checkout'}</Button>
</AppLink>
</div>
<Table
className="cart-table"
columns={[
{
className: 'cart-table',
dataIndex: 'product',
key: 'product',
render: (text, record) => (
<div className="product-display">
<img src={record.image} />
<p>{record.product}</p>
</div>
),
title: 'Product',
width: '25%',
},
{
className: 'cart-table',
dataIndex: 'price',
key: 'price',
title: 'Price',
},
{
className: 'cart-table',
dataIndex: 'quantity',
key: 'quantity',
render: (text, record) => (
<div className="quantity-container">
<div className="quantity-value">{record.quantity}</div>
<div className="quantity-actions">
<Icon
type="caret-up"
title="Add"
onClick={() => this.handleQuantityChange(record, 'add')}
/>
<Icon
type="caret-down"
title="Reduce"
onClick={() => this.handleQuantityChange(record, 'sub')}
/>
</div>
</div>
),
title: 'Quantity',
},
{
className: 'cart-table',
dataIndex: 'amount',
key: 'amount',
render: (text, record) => `${record.price * record.quantity}`,
title: 'Amount',
},
{
className: 'cart-table',
key: 'action',
render: (text, record) => (
<Popconfirm
title="Are you sure you want to remove item?"
onConfirm={() => this.handleRemove(record)}
>
<a href="javascript:;" className="danger">{`Remove`}</a>
</Popconfirm>
),
title: 'Action',
},
]}
dataSource={values}
rowKey={record => record.id}
/>
</div>
);
}
}
const mapStateToProps = state => ({
cart: getCart(state),
});
const mapDispatchToProps = dispatch => ({
actions: bindActionCreators(actions, dispatch),
});
export default connect(
mapStateToProps,
mapDispatchToProps,
)(Cart);
actions.js
import { UPDATE_CART_INFO, UPDATE_CART_LIST } from './actionTypes';
/**
* Triggers request to update cart items
*
* @function
* @param {Object} payload An object of cart dataSource
* @return {void} The {@link actionTypes.UPDATE_CART_LIST UPDATE_CART_LIST} action.
*/
export const updateCartList = payload => ({
payload,
type: UPDATE_CART_LIST,
});
/**
* Triggers request to update cart details
*
* @function
* @param {Object} payload An object of captured cart details
* @return {void} The {@link actionTypes.UPDATE_CART_INFO UPDATE_CART_INFO} action.
*/
export const updateCartInfo = payload => ({
payload,
type: UPDATE_CART_INFO,
});
选择器
import { NAME } from './constants';
/**
* Selects the <tt>user</tt> key.
*
* @function
* @param {Object} state - redux store state
* @return {Number} the state data of the signin which contains user data
* {@link module:cart/constants::INITIAL_STATE constants::INITIAL_STATE}).
*/
export const getCart = state => state[NAME].cart;
答案 0 :(得分:1)
updateCartInfo(cartItem, list)
带有两个参数:cartItem
和list
。
它要做的第一件事是尝试解构cartItem
并从中获取id
属性。
但是,在这里您不带参数地调用该函数:
componentDidUpdate(prevProp) {
const { cart: newList } = this.props;
const { cart: oldList } = prevProp;
if (newList != oldList) {
const { updateCartInfo } = this.props.actions;
updateCartInfo(); // <------------ HERE
}
}
因此cartItem
是undefined
,而javascript无法读取id
的属性undefined
。
function updateCartInfo(cartItem, list) {
if(cartItem && list){
const { id } = cartItem;
const newList = new Map([...list.entries()]);
newList.set(id, cartItem);
return newList;
}
}
编辑:
尝试一下:
componentDidUpdate(prevProp) {
const { cart: newList } = this.props;
const { cart: oldList } = prevProp;
if (newList != oldList) {
const { updateCartInfo } = this.props.actions;
updateCartInfo(null, newList); // <------------ HERE
}
}
和:
function updateCartInfo(cartItem, list) {
if(cartItem && list){
const { id } = cartItem;
const newList = new Map([...list.entries()]);
newList.set(id, cartItem);
return newList;
} else if (list) { // <----- HERE
return list; // <----- HERE
}
}
除此之外,您还可以重新考虑为什么要调用不带参数的updateCartList()
函数,并调整代码逻辑使其更适合于此。但是我认为这超出了堆栈溢出问题的范围。