我有一个看起来像这样的反应组件:
class MyComponent extends Component {
incrementQty = () => {
// calls this.setState({....})
}
setQty (qty) => {
for (....) {
this.incrementQty()
}
}
}
我的问题是在循环中的最后一次调用之前状态不会更新,我知道setState是异步的,我不能在这里使用redux来在调度动作后重新渲染组件。
有没有人有解决方案,谢谢。
答案 0 :(得分:2)
状态应该尽可能少地更新,如果你在循环中快速更新它将导致问题,因为它试图根据状态变化重新渲染。
如果您根据'incrementQty'中的当前状态更新状态,这也会导致问题,因为渲染周期尚未完成,并且每个循环都不会更新当前状态。
要解决此问题,请先计算新数量,然后再更新状态:
class MyComponent extends Component {
setQty (qty) => {
let newQuantity = 0; //or this.state.quantity?
for (....) {
newQuantity++;
}
this.setState({quantity:newQuantity}
}
}
P.S。无论如何你似乎都要将数量传递给setQty,你确定你不只是想使用'this.setState({quantity:qty});'?
答案 1 :(得分:0)
内部状态变化不会同步发生,你是对的。在当前函数调用之后,对内部状态的任何更改都会排队,直到至少。所以正在发生的事情是你对setState
的几次调用被合并为一个大的增量。
在重新渲染之前,您需要再次访问状态是什么?而不是仅仅增加数量,最好只在组件状态中设置数量,而不是使用for循环。如果您希望一次增加一个值,请使用生命周期方法 - 可能是componentDidUpdate
- 在每次渲染时递增第二个计数器,直到达到qty
的正确值。
答案 2 :(得分:0)
您可以使用原子setState
的回调形式。 Demo
Docs
this.setState((prevState, props) => { return {myInteger: prevState.myInteger + props.step}; });
它更新了状态" redux"方式,但没有减少。
class MyComponent extends Component {
incrementQty = () => {
this.setState((prevState) => {
return {counter: prevState.counter + 1}
})
}
setQty (qty) => {
for (....) {
this.incrementQty()
}
}
}
完整示例
const { Component } = React
const { render } = ReactDOM
class App extends Component {
constructor(props, ctx) {
super(props, ctx);
this.state = {
counter: 0
}
this.inc = this.inc.bind(this);
this.dec = this.dec.bind(this);
}
// this works for multiple calls
inc() {
this.setState((prevState) => {
return {
counter: prevState.counter + 1
}
})
}
// this doesn't work on subsequent calls
dec() {
this.setState({
counter: this.state.counter - 1
})
}
up(qty) {
while(qty--) {
this.inc()
}
}
down(qty) {
while(qty--) {
this.dec()
}
}
render() {
const { counter } = this.state
return (
<div>
<div>
<button type="button" onClick={() => this.up(10) }>+10</button>
<button type="button" onClick={() => this.up(5) }>+5</button>
<button type="button" onClick={this.inc}>+</button>
<button type="button" onClick={this.dec}>-</button>
<button type="button" onClick={() => this.down(5) }>-5</button>
<button type="button" onClick={() => this.down(10) }>-10</button>
</div>
{counter}
</div>
)
}
}
render(<App />, document.getElementById('content'))