连续 setState 不能按预期工作
continuous setState doesn't work as expected
我有下面一段代码 -
class Sum extends React.Component {
constructor(props) {
super(props)
this.state = { a : 0 }
}
// let's call this ADD-1
add = () => {
this.setState({ a: this.state.a + 1 })
this.setState({ a: this.state.a + 2 })
this.setState({ a: this.state.a + 3 })
}
render() {
return (<div>
<button onClick={this.add}> click me </button>
<div> sum {this.state.a} </div>
</div>)
}
}
这是在点击按钮时呈现的
sum = 3
我希望它会呈现 sum = 6
即 1 + 2 + 3
此外,如果我将 add
方法更改为类似适应 prevState
竞争条件的方法 -
// let's call this ADD-2
add = () => {
this.setState({ a: this.state.a + 1 })
this.setState({ a: this.state.a + 2 })
this.setState(prevState => ({ a: prevState.a + 1 }))
this.setState(prevState => ({ a: prevState.a + 4 }))
}
它呈现 sum = 7
而我希望 sum = 8
即 (1 + 2 + 1 + 4)
现在我想到两个问题:-
1) 为什么我们看到的结果是上面提到的结果,而不是我预期的结果?
2) 为什么我在 UI 中看不到加法的转换?
假设我们考虑标记为 ADD-1
的方法,我应该看到类似 sum = 1
然后 sum = 3
然后 sum = 6
的东西。是因为批处理更新但批处理将它们放入执行队列中,我认为它不会覆盖任何内容。
"React may batch multiple setState() calls into a single update for performance."
来自Docs
确保在更新依赖于当前状态时将函数传递给 setState
,这样它就不会被后续 setState
.
覆盖
例子
class App extends React.Component {
state = { a: 0 };
add = () => {
this.setState(previousState => {
return { a: previousState.a + 1 };
});
this.setState(previousState => {
return { a: previousState.a + 2 };
});
this.setState(previousState => {
return { a: previousState.a + 3 };
});
};
render() {
return (
<div>
<button onClick={this.add}> click me </button>
<div> sum {this.state.a} </div>
</div>
);
}
}
状态更新可能是异步的。检查此 .
在 Dan abramov 的 中,声明一次事件调用中的状态更新只会在事件结束时产生一次重新渲染。
no matter how many setState() calls in how many components you do
inside a React event handler, they will produce only a single
re-render at the end of the event.
并且批处理仅发生在 React 事件处理程序中的状态更新,即批处理不会发生在 AJAX 调用
中
promise.then(() => {
// We're not in an event handler, so these are flushed separately.
this.setState({a: true}); // Re-renders with {a: true, b: false }
this.setState({b: true}); // Re-renders with {a: true, b: true }
this.props.setParentState(); // Re-renders the parent
});
但是您可以通过将回调传递给 setState
方法来实现您想要的效果
add = () => {
this.setState({ a: this.state.a + 1 },
() => {
this.setState({ a: this.state.a + 2 },
() => {
this.setState({ a: this.state.a + 3 })
})
})
}
以上将return sum = 6.
何时不在 setState 中使用回调:
PureComponent
and shouldComponentUpdate
can be used to tune up a
component’s performance. They work by preventing lifecycle methods
from firing when props and state haven’t changed.
The setState
callback fires regardless of what shouldComponentUpdate
returns. So, the setState
callback will fire, even when state hasn’t
changed.
状态更改只能通过 setState 发生,但如果您在 setState (this.state.a + 1) 之前访问和修改 this.state,它不会反映。所以每次你访问 this.state.a 它都会得到 0 即初始值。
add = () => {
this.setState({ a: this.state.a + 1 }) // 0 + 1
this.setState({ a: this.state.a + 2 }) // 0 + 2
this.setState({ a: this.state.a + 3 }) // 0 + 3
}
this.setState((previousState) => { // change state using previousState} );
这是更新状态的方法
我有下面一段代码 -
class Sum extends React.Component {
constructor(props) {
super(props)
this.state = { a : 0 }
}
// let's call this ADD-1
add = () => {
this.setState({ a: this.state.a + 1 })
this.setState({ a: this.state.a + 2 })
this.setState({ a: this.state.a + 3 })
}
render() {
return (<div>
<button onClick={this.add}> click me </button>
<div> sum {this.state.a} </div>
</div>)
}
}
这是在点击按钮时呈现的
sum = 3
我希望它会呈现 sum = 6
即 1 + 2 + 3
此外,如果我将 add
方法更改为类似适应 prevState
竞争条件的方法 -
// let's call this ADD-2
add = () => {
this.setState({ a: this.state.a + 1 })
this.setState({ a: this.state.a + 2 })
this.setState(prevState => ({ a: prevState.a + 1 }))
this.setState(prevState => ({ a: prevState.a + 4 }))
}
它呈现 sum = 7
而我希望 sum = 8
即 (1 + 2 + 1 + 4)
现在我想到两个问题:-
1) 为什么我们看到的结果是上面提到的结果,而不是我预期的结果?
2) 为什么我在 UI 中看不到加法的转换?
假设我们考虑标记为 ADD-1
的方法,我应该看到类似 sum = 1
然后 sum = 3
然后 sum = 6
的东西。是因为批处理更新但批处理将它们放入执行队列中,我认为它不会覆盖任何内容。
"React may batch multiple setState() calls into a single update for performance."
来自Docs
确保在更新依赖于当前状态时将函数传递给 setState
,这样它就不会被后续 setState
.
例子
class App extends React.Component {
state = { a: 0 };
add = () => {
this.setState(previousState => {
return { a: previousState.a + 1 };
});
this.setState(previousState => {
return { a: previousState.a + 2 };
});
this.setState(previousState => {
return { a: previousState.a + 3 };
});
};
render() {
return (
<div>
<button onClick={this.add}> click me </button>
<div> sum {this.state.a} </div>
</div>
);
}
}
状态更新可能是异步的。检查此
在 Dan abramov 的
no matter how many setState() calls in how many components you do inside a React event handler, they will produce only a single re-render at the end of the event.
并且批处理仅发生在 React 事件处理程序中的状态更新,即批处理不会发生在 AJAX 调用
中promise.then(() => {
// We're not in an event handler, so these are flushed separately.
this.setState({a: true}); // Re-renders with {a: true, b: false }
this.setState({b: true}); // Re-renders with {a: true, b: true }
this.props.setParentState(); // Re-renders the parent
});
但是您可以通过将回调传递给 setState
方法来实现您想要的效果
add = () => {
this.setState({ a: this.state.a + 1 },
() => {
this.setState({ a: this.state.a + 2 },
() => {
this.setState({ a: this.state.a + 3 })
})
})
}
以上将return sum = 6.
何时不在 setState 中使用回调:
PureComponent
andshouldComponentUpdate
can be used to tune up a component’s performance. They work by preventing lifecycle methods from firing when props and state haven’t changed.The
setState
callback fires regardless of whatshouldComponentUpdate
returns. So, thesetState
callback will fire, even when state hasn’t changed.
状态更改只能通过 setState 发生,但如果您在 setState (this.state.a + 1) 之前访问和修改 this.state,它不会反映。所以每次你访问 this.state.a 它都会得到 0 即初始值。
add = () => {
this.setState({ a: this.state.a + 1 }) // 0 + 1
this.setState({ a: this.state.a + 2 }) // 0 + 2
this.setState({ a: this.state.a + 3 }) // 0 + 3
}
this.setState((previousState) => { // change state using previousState} );
这是更新状态的方法