[英]How do I update the redux state without running into errors
使用某些方法時,我需要更新Redux存儲。 我可以在掛載並調用updateCartList()
時在組件中呈現虛擬數據,但是當我嘗試使用componentDidUpdate()
updateCartInfo()
進行更新並調用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;
updateCartInfo(cartItem, list)
兩個參數: cartItem
和list
。 它做的第一件事是嘗試解構cartItem
並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無法讀取undefined
的屬性id
。
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()
函數,並調整代碼邏輯使其更適合於此。 但是在我看來,這超出了堆棧溢出問題的范圍。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.