React setState后state未更新,点击按钮需两次才生效问题咨询
React setState异步更新导致状态未即时生效的解决方案
先看你提供的代码:
class App extends React.Component{ constructor() { super(); this.state = { route: "Branches", adding: false, user: '', table: [], Branche: '', } } OnAccessBranch = (event) => { this.setState({Branche: event.target.name, route: event.target.id}) console.log(this.state) this.CheckTable(this.state.route) console.log(this.state) } CheckTable = (route) => { switch(route){ case "Guichets": this.setState({table: Guichets}) console.log(this.state.route) break; case "Services": this.setState({table: Services}) console.log(this.state.route) break; case "Branches": this.setState({table: Branches}) console.log(this.state.route) break; default: this.setState({table: Branches}) } } }
问题根源
React的setState是异步批量更新机制,调用后不会立刻修改this.state,而是将更新请求放入队列,等待合适时机统一处理。所以你在setState后直接console.log(this.state),拿到的还是更新前的旧状态;调用CheckTable(this.state.route)时,this.state.route同样是旧值,导致CheckTable逻辑执行错误,必须第二次点击才能用上一次的新值触发正确逻辑。
解决方案
方案一:利用setState的回调函数
setState支持第二个参数,是状态更新完成后的回调函数,在这里可以拿到最新的state:
OnAccessBranch = (event) => { const newRoute = event.target.id; const newBranche = event.target.name; this.setState( { Branche: newBranche, route: newRoute }, // 状态更新完成后执行 () => { console.log(this.state); // 此处为最新状态 this.CheckTable(this.state.route); console.log(this.state); } ); }
方案二:直接使用事件中获取的新值(更高效)
既然已经从event中拿到了新的route和Branche,直接将这些值传给CheckTable即可,无需等待state更新:
OnAccessBranch = (event) => { const newRoute = event.target.id; const newBranche = event.target.name; this.setState({ Branche: newBranche, route: newRoute }); this.CheckTable(newRoute); // 直接使用新route,不依赖state }
另外,CheckTable里的console.log(this.state.route)也存在同样的异步问题,解决方式有两种:
CheckTable = (route) => { let targetTable; switch(route){ case "Guichets": targetTable = Guichets; break; case "Services": targetTable = Services; break; case "Branches": targetTable = Branches; break; default: targetTable = Branches; } this.setState({ table: targetTable }, () => { console.log(this.state.route); // 此处能拿到最新route }); // 或者直接打印传入的route参数,它本身就是最新值 console.log(route); }
补充说明
React将setState设计为异步,是为了合并多次状态更新,减少DOM重绘次数,提升应用性能。记住不要在调用setState后立即访问this.state,要么使用回调函数,要么直接使用准备更新的变量值。
内容的提问来源于stack exchange,提问作者3idoudi
相关产品推荐
相关产品推荐

