dar*_*urf 112 javascript state setstate reactjs
我知道React可以异步和批量执行状态更新以进行性能优化.因此,在调用之后,您永远不能相信要更新的状态setState.但是你可以信任的反应更新相同的顺序状态setState被称为对
考虑单击以下示例中的按钮:
1.是否有可能a是假的,b对于:
class Container extends React.Component {
constructor(props) {
super(props);
this.state = { a: false, b: false };
}
render() {
return <Button onClick={this.handleClick}/>
}
handleClick = () => {
this.setState({ a: true });
this.setState({ b: true });
}
}
Run Code Online (Sandbox Code Playgroud)
2.是否有可能a是假的,b对于:
class SuperContainer extends React.Component {
constructor(props) {
super(props);
this.state = { a: false };
}
render() {
return <Container setParentState={this.setState.bind(this)}/>
}
}
class Container extends React.Component {
constructor(props) {
super(props);
this.state = { b: false };
}
render() {
return <Button onClick={this.handleClick}/>
}
handleClick = () => {
this.props.setParentState({ a: true });
this.setState({ b: true });
}
}
Run Code Online (Sandbox Code Playgroud)
请记住,这些是我的用例的极端简化.我意识到我可以这样做,例如在示例1中同时更新两个状态参数,以及在示例2中的第一个状态更新的回调中执行第二个状态更新.但是,这不是我的问题,而且我只对React执行这些状态更新的定义方式感兴趣,没有别的.
任何由文档支持的答案都非常感谢.
Dan*_*mov 288
我在React工作.
TLDR:
但是你能相信React以与调用setState相同的顺序更新状态
- 相同的组件?
是.
- 不同的组件?
是.
该订单的更新总是尊重.你是否看到它们之间的中间状态取决于你是否在一个批次内.
目前(React 16及更早版本),默认情况下仅对React事件处理程序内的更新进行批处理.在您需要时,有一个不稳定的API可以强制在事件处理程序之外进行批处理.
在未来的版本(可能是React 17及更高版本)中,React默认会批量处理所有更新,因此您不必考虑这一点.与往常一样,我们将在React博客和发行说明中公布有关此内容的任何更改.
理解这一点的关键是,无论setState()你在React事件处理程序中执行多少组件调用多少次,它们在事件结束时只会产生一次重新渲染.这对于大型应用程序的良好性能至关重要,因为在处理click事件时,如果Child和Parent每次调用setState(),您都不想重新渲染Child两次.
在两个示例中,setState()调用都发生在React事件处理程序中.因此,它们总是在事件结束时被冲洗在一起(并且您没有看到中间状态).
更新始终按其发生的顺序浅层合并.因此,如果第一次更新是{a: 10},第二次更新,{b: 20}第三次更新{a: 30},则呈现状态将是{a: 30, b: 20}.对同一状态键的更新更新(例如,a在我的示例中)总是"获胜".
this.state当我们在批处理结束时重新呈现UI时,对象会更新.因此,如果您需要根据以前的状态更新状态(例如递增计数器),则应使用setState(fn)提供先前状态的功能版本,而不是读取this.state.如果你对这个原因感到好奇,我在这篇评论中对此进行了深入解释.
在您的示例中,我们不会看到"中间状态",因为我们在React事件处理程序中启用了批处理(因为React"知道"我们何时退出该事件).
但是,在React 16和早期版本中,默认情况下,React事件处理程序之外没有默认批处理.因此,如果在您的示例中我们有一个AJAX响应处理程序而不是handleClick,则每个setState()都会在发生时立即处理.在这种情况下,是的,你会看到一个中间状态:
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
});
Run Code Online (Sandbox Code Playgroud)
我们意识到行为不同取决于你是否在事件处理程序中是不方便的.这将在未来的React版本中更改,默认情况下将批量处理所有更新(并提供一个选择性API以同步刷新更改).在我们切换默认行为(可能在React 17中)之前,您可以使用一个API来强制批处理:
promise.then(() => {
// Forces batching
ReactDOM.unstable_batchedUpdates(() => {
this.setState({a: true}); // Doesn't re-render yet
this.setState({b: true}); // Doesn't re-render yet
this.props.setParentState(); // Doesn't re-render yet
});
// When we exit unstable_batchedUpdates, re-renders once
});
Run Code Online (Sandbox Code Playgroud)
内部React事件处理程序都被包装,unstable_batchedUpdates这就是默认情况下它们被批处理的原因.请注意,将更新包装unstable_batchedUpdates两次无效.当我们退出最外面的unstable_batchedUpdates呼叫时刷新更新.
该API是"不稳定的",因为我们将在默认情况下启用批处理时将其删除.但是,我们不会在次要版本中删除它,因此如果您需要在React事件处理程序之外的某些情况下强制批处理,则可以安全地依赖它直到React 17.
总而言之,这是一个令人困惑的主题,因为React默认只在事件处理程序内批处理.这将在未来版本中发生变化,然后行为将变得更加直截了当.但解决方案不是批量减少,而是默认批量更多.这就是我们要做的.
同一周期内的多个调用可以一起批处理。例如,如果您尝试在同一周期内多次增加物料数量,则将导致相当于:
Object.assign(
previousState,
{quantity: state.quantity + 1},
{quantity: state.quantity + 1},
...
)
Run Code Online (Sandbox Code Playgroud)
https://reactjs.org/docs/react-component.html
这实际上是一个非常有趣的问题,但答案应该不会太复杂。在媒体上有一篇很棒的文章有答案。
1)如果这样做
this.setState({ a: true });
this.setState({ b: true });
Run Code Online (Sandbox Code Playgroud)
我不认为会出现的情况下a会true和b会false因为配料。
但是,如果b取决于,a则确实可能存在无法获得预期状态的情况。
// assuming this.state = { value: 0 };
this.setState({ value: this.state.value + 1});
this.setState({ value: this.state.value + 1});
this.setState({ value: this.state.value + 1});
Run Code Online (Sandbox Code Playgroud)
处理完所有上述调用后,this.state.value将为1,而不是您期望的3。
这是在文章中提到的: setState accepts a function as its parameter
// assuming this.state = { value: 0 };
this.setState((state) => ({ value: state.value + 1}));
this.setState((state) => ({ value: state.value + 1}));
this.setState((state) => ({ value: state.value + 1}));
Run Code Online (Sandbox Code Playgroud)
这会给我们 this.state.value === 3
| 归档时间: |
|
| 查看次数: |
28994 次 |
| 最近记录: |