方案1:
const { foo } = this.state;
方案2:
this.setState(({ foo }) => { ... });
在这两种情况下,foo
是否保证相同?还是setState
会异步运行并根据其他setState
返回不同的值?
答案 0 :(得分:2)
当您使用this.setState
后立即访问状态时,状态可能是状态,因为this.setState
是async
。
如果需要基于更新的状态(即,在调用this.state
之后进行计算),则可以将方法的第二个参数用作该方法,该方法是在提交状态更改后触发的回调。 / p>
this.setState(updateState, () => {
const { foo } = this.state;
console.log(foo); // updated foo
});
function updatedState({ foo }) {
// you can be sure that `foo`
// is from the previous state
// before setState is called
}
答案 1 :(得分:2)
如React docs所述:
setState()并不总是立即更新组件。它可能 批处理或将更新推迟到以后。这使得阅读this.state 在调用setState()之后立即发生潜在的陷阱。相反,使用 componentDidUpdate或setState回调(setState(updater, 回调)),保证在更新后都会触发 已应用。
因此,我们可以使用 setState
的第二个参数来传递回调,在该回调中我们执行逻辑,这取决于具有foo的更新值。但是,您最初的问题是const { foo } = this.state;
中foo的值和this.setState(({ foo }) => { ... });
中foo的值是否相同。
为了对此进行检查,我们可以比较执行 setState
,然后执行 this.state.foo
和 setState
后跟另一个 setState
(第二个将仅记录foo的值而不是对其进行突变)。请参考以下代码段:
class Example extends React.Component {
constructor() {
super();
this.state = {
foo: 0,
boo: 0
}
}
handleClickSetState = () => {
this.setState(({foo}) => ({foo: foo+1}));
this.setState(({foo}) => console.log("inside setState. foo: ", foo));
}
handleClickState = () => {
this.setState(({boo}) => ({boo: boo+1}));
console.log("outside setState. boo: ", this.state.boo)
}
render() {
return <React.Fragment>
<button onClick={this.handleClickState}>Test state</button>
<button onClick={this.handleClickSetState}>Test setState</button>
</React.Fragment>
}
}
ReactDOM.render(<Example />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
我们可以看到“状态案例”落后1,这是我们期望的,因为 setState
是异步的(而且我们没有使用的第二个参数setState
)。但是,“ setState情况”表明,即使我们未在setState中使用第二个参数回调,也始终显示正确的值。
最后,const { foo } = this.state;
始终会为您提供foo的立即值,而与挂起状态合并无关,而this.setState(({ foo }) => { ... });
似乎将在执行回调之前首先完成挂起的更新,这意味着foo将始终具有最新值。
答案 2 :(得分:1)
setState
是异步的,从setState
中使用状态取值是潜在的错误源。 setState
可以接受多个参数。它可以只接受新状态,接受旧状态+道具并返回新状态,新状态和设置新状态后要运行的函数的回调,或组合使用。示例:
this.setState(
// function taking previous state + props,
// which should return updated state.
// this could also just be an object with
// the new state, if you don't need to rely
// on previous state.
(previousState, props) => {
if (previousState.something) {
return { something: somethingElse }
} else {
return { something: anotherThing }
}
}, () => {
// safe to use new state here,
// since state has been updated.
// but it's recommended to use
// componentDidUpdate instead!
})