我正在建立一个包含物品清单的购物车。用户可以更新每个项目的数量,从而调整项目的价格。 同样在购物车的底部,用户必须支付的所有价格的总和应为总计。
我的问题是如何获取所有更新的价格,对其进行汇总并显示总计。当用户更改每件商品的数量时,如何使总计进行自我更新?
class Item extends Component {
constructor(props) {
super(props);
this.state = {
quantity: 1,
price: parseFloat(this.props.product.price.replace(/\$|£|/g, '')).toFixed(2)
};
this.onChangeHandler = this.onChangeHandler.bind(this);
}
onChangeHandler(event) {
const target = event.target;
this.props.updateSubtotal(this.props.product.price, event.target.value);
this.setState((prevState, props) => ({
quantity: target.value,
price: props.subtotal
}));
}
render() {
const { product, index } = this.props;
return (
<li>
<h3>{product.name}</h3>
<Input
onChange={this.onChangeHandler}
name="product-quantity"
value={this.state.quatity}
/>
<span>
{'$' + this.state.price}
</span>
</li>
);
}
}
const mapStateToProps = state => ({
subtotal: state.products.subtotal
});
export default connect(mapStateToProps, { updateSubtotal })(Item);
// UPDATE TOTAL PRICE
export const updateTotal = result => dispatch => {
// Don't what to do here. Or maybe there's a better solution...
const newTotal = [];
newTotal.push(result);
return dispatch({
type: UPDATE_TOTAL,
total: newTotal
});
};
// UPDATE ITEM PRICE BY QUANTITY
export const updateSubtotal = (price, multiplier) => dispatch => {
const result = computePrice(price, multiplier);
// Update cart total
dispatch(updateTotal(result));
return dispatch({
type: UPDATE_SUBTOTAL,
subtotal: result
});
};
const INITIAL_STATE = {
total: [],
subtotal: 1,
products: [],
loading: false
};
const productsReducer = (state = INITIAL_STATE, action) => {
switch (action.type) {
// Update item price
case Types.UPDATE_SUBTOTAL:
return {
...state,
subtotal: action.subtotal
};
// Update total
case Types.UPDATE_TOTAL:
return {
...state,
total: action.total // -> I'm stuck here
};
default:
return state;
}
};
export default productsReducer;
答案 0 :(得分:-1)
您无需使用其他操作即可更新总价。每当您将新商品添加到购物车时,您的状态都会更改,是吗?在这种情况下,您只需要编写一个看起来像这样的util:
// utils.js
export const totalPrice = (state) => {
const products = state.products;
const reducer = (currentTotal, product) => currentTotal + product.price;
return products.reduce(reducer);
};
然后,在您的容器中执行以下操作:
// Cart.js
import React from 'react';
import { connect } from 'react-redux';
import { totalPrice } from './utils'; // or wherever else
const Cart = ({ total }) => (
<div>
{`Your total is ${total}`}
</div>
);
const mapStateToProps = state => ({
total: totalPrice(state),
});
export default connect(
mapStateToProps,
)(Cart);
每当您向products
添加商品时,价格就会自动更新。
** EDIT **
根据您在注释中的要求,如果您想将total
保留在减速器中,则这是另一种方法。请注意,您将不再需要执行updateTotal
操作。
// reducers.js
const INITIAL_STATE = {
total: 0, // note this is not an array.
subtotal: 0, // I also set this to 0 instead.
products: [],
loading: false
};
const productsReducer = ( state = INITIAL_STATE, action ) => {
switch(action.type) {
case Types.UPDATE_SUBTOTAL:
const newSubtotal = action.subtotal;
const newTotal = state.total + (newSubtotal - state.subtotal);
return {
...state,
subtotal: newSubtotal,
total: newTotal,
};
}
default:
return state;
};
即使上述方法可行,我还是建议您调度一个操作来更新products
而不是价格,并更新该操作所导致的所有相关内容。如果您考虑一下,每当将商品添加到products
时,更新总价/小计价格,数量等是很有意义的。
另一件事:您在化纸机中使用的印象spread syntax对我来说是浅拷贝。您需要注意存储在products
数组中的内容,以免错误地改变旧状态。请记住,您始终想返回一个新的状态对象。您可以了解有关here的更多信息。