我正在使用以下方法从保存的会话中加载数据:
componentDidMount() {
if (JSON.parse(localStorage.getItem('savedData')) !== null) {
this.setState({
cartItems: JSON.parse(localStorage.getItem('savedData')),
totalPrice: this.getPriceOnLoad(),
totalItems: this.getItemsOnLoad(),
});
}
}
cartItems
是一个对象数组。似乎是之前更新的
this.getPriceOnLoad();
this.getItemsOnLoad();
函数被调用,例如this.getPriceOnLoad
函数:
getPriceOnLoad() {
let itemsPrice = 0;
for (let i = 0; i <= this.state.cartItems.length - 1; i++) {
itemsPrice += this.state.cartItems[i].quantity * this.state.cartItems[i].price;
}
return itemsPrice;
}
但是,在getPriceOnLoad
函数中,this.state.cartItems.length
等于0,因此不会执行for循环。我可以在React开发工具中看到此数组有一定长度。是否因为componentDidMount()
正在同步执行状态更改而无法立即看到更新的数组?所以我的问题是数组初始化后如何更新商品的价格和数量?
答案 0 :(得分:4)
您的状态未按顺序更新。为此,您可以将cartItems
存储在一个临时值中,并将其发送给每个函数:
componentDidMount() {
if (JSON.parse(localStorage.getItem('savedData')) !== null) {
const cartItems = JSON.parse(localStorage.getItem('savedData'))
this.setState({
cartItems, //Short syntax for 'cartItems: cartItems'
totalPrice: this.getPriceOnLoad(cartItems),
totalItems: this.getItemsOnLoad(cartItems),
});
}
}
您还可以通过使用reduce
使功能大大缩短:
this.setState({
cartItems,
totalPrice: cartItems.reduce((total, item) => total + (item.quantity * item.price), 0),
totalItems: cartItems.reduce((total, item) => total + item.quantity, 0),
});
您也可以向我们展示您的第二个功能吗?可能也会对其进行优化。完成。
答案 1 :(得分:2)
您做的错误的事情是尝试在函数中使用状态值来定义状态。
您有2种解决方法:
1)使用<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.min.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<link href="~/lib/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" />
<script src="~/lib/bootstrap/dist/js/bootstrap.min.js"></script>
<style>
#chart_container{
width:400px;
height:400px;
border: 1px solid #ddd;
padding:1px;
border-radius:4px;
}
</style>
</head>
<body>
<div id="chart_container">
<canvas id="bar_chart"></canvas>
</div>
<script>
var purchaseOrderID = @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(ViewBag.PurchaseOrderID));
var qtyOrdered = @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(ViewBag.QtyOrdered));
@*@{ var purchaseOrderID = ViewBag.PurchaseOrderID;}
@{ var qtyOrdered = ViewBag.QtyOrdered;}*@
var ctx = $('#bar_chart');
var barchart = new Chart(ctx, {
type: 'bar',
data: {
labels: purchaseOrderID,
dataset: [{
label: "Bar Chart example",
data:qtyOrdered,
backgroundColor: ["rgba(244,166,54,0.5)", "rgba(145,65,72,0.5)", "(74,25,92,0.5)"],
borderColor: ["rgba(244,166,54,0.5)", "rgba(145,65,72,0.5)", "(74,25,92)"],
borderwidth: 1
}]
},
options: {
maintainAspectRatio: false,
scales: {
xAxes: [{ ticks: { beginAtZero: true } }]
},
legend: { display: false }
},
});
</script>
</body>
</html>
中的回调函数,然后使用新数据再次设置状态(我认为这不是最佳方法)
setState
2)将值发送到您的函数
componentDidMount() {
if (JSON.parse(localStorage.getItem('savedData')) !== null) {
const cartItems = JSON.parse(localStorage.getItem('savedData'))
this.setState({
cartItems
}, ()=> {
this.setState({
totalPrice: this.getPriceOnLoad(cartItems),
totalItems: this.getItemsOnLoad(cartItems),
});
})
}
}
答案 2 :(得分:0)
getPriceOnLoad()
在执行this.setState之前执行。因此,您无法在this.state
中引用getPriceOnLoad()
。
调用this.setState({})
时,JS首先需要为setState()
函数生成对象。表示您要引用的功能先运行,然后运行this.setState()
。
在任何情况下,this.setState()
是一个异步函数,因此this.state
在执行setState()
之后不能直接使用。