React Native中如何等待多个setState执行完成后再运行后续代码
问题原因
React 中setState是异步批量执行的,连续调用多次setState时,React会把所有更新合并后再一次性修改状态,不会同步更新this.state,因此你在setState队列之后直接写的判断逻辑,读取到的是更新前的旧状态值,才会出现提前触发的问题。
最优实现方案
你不需要多次调用setState,可以先跑完所有校验逻辑,组装好完整的待更新状态对象,一次性执行setState,再通过setState的第二个回调参数(状态更新完成后自动触发)执行跳转判断,逻辑更清晰性能也更好,修改后代码如下:
validate = () => { this.changedNumber(); // 先声明变量存储校验结果,不直接修改state let error_spaceName = null; let error_phone = null; // 校验空间名称 if (!this.state.spaceName) { error_spaceName = "Name of space is required"; } else if (this.state.spaceName.length < 3) { error_spaceName = "Name of space should be of minimum 3 character length"; } // 校验手机号 if (!this.state.code) { error_phone = "Phone Number is required"; } else if (isValidNumber(Number(this.state.code)) === false) { error_phone = "Contact number should be a Kuwait number"; } // 一次性更新所有状态,第二个参数是更新完成的回调 this.setState({ error_spaceName, error_phone }, () => { // 回调内读取的是最新的state值 if (this.state.error == null && this.state.error_spaceName == null && this.state.error_phone == null) { this.props.navigation.navigate("LocationScreen") } }) }
其他场景补充
如果确实有必须分多次调用setState的场景,可以把setState封装为Promise,再用Promise.all等待所有更新完成后再执行后续逻辑,封装参考如下:
// 封装setState为Promise asyncSetState = (stateObj) => { return new Promise(resolve => { this.setState(stateObj, resolve) }) } // 调用时用Promise.all等待 validate = async () => { this.changedNumber(); const updateQueue = []; // 把所有setState调用推入队列 if (!this.state.spaceName) { updateQueue.push(this.asyncSetState({error_spaceName: "Name of space is required"})) } // ... 其他校验逻辑的setState同样推入updateQueue // 等待所有更新完成 await Promise.all(updateQueue); // 再执行判断 if (this.state.error == null && this.state.error_spaceName == null && this.state.error_phone == null) { this.props.navigation.navigate("LocationScreen") } }
针对你当前的校验场景,第一种合并更新的方案更推荐。
内容的提问来源于stack exchange,提问作者Arjun
相关产品推荐
相关产品推荐

