React setState未更新状态:登录后组件无法渲染问题求助
嘿,问题出在React setState的异步特性上!
你之所以在调用setState后立刻打印state还是旧值,核心原因是React类组件中的setState是异步操作——它不会在你调用的瞬间就立刻更新state,而是会把多个setState请求攒起来批量处理,以此优化性能。所以你在this.setState(...)之后马上console.log,拿到的肯定还是更新前的旧状态。
为什么会这样?
React为了避免频繁触发组件重渲染(毕竟重渲染很消耗性能),会合并多个setState调用,等到合适的时机再统一更新state并触发重渲染。这就导致你在setState之后立刻读取this.state,结果还是旧值。
怎么解决?
方法一:用setState的回调函数
setState支持第二个参数,是一个回调函数,这个函数会在state更新完成、组件重渲染之后执行,在这里你就能拿到最新的state了。修改你的App.js里的login方法:
login = (username) => { console.log('输入的用户名', username) console.log('更新前的username state', this.state.username) this.setState({ loggedIn: true, username: username }, () => { // 这里是state更新完成后的回调 console.log('更新后的username state', this.state.username) console.log('更新后的loggedIn状态', this.state.loggedIn) }); }
方法二:在render里查看最新state
组件的render方法会在state更新后自动触发,你可以在render里打印state,这里肯定是最新的:
render() { console.log('当前最新state:', this.state) return ( <div className="container"> <h1>Lightning Talks!</h1> <Login login={this.login}/> {this.state.loggedIn ? <LightningTalkRender/> : null} {/* 注意组件首字母要大写! */} <h3 className="form-header"> Submit your talk</h3> <Form postInApp={this.postInApp}/> </div> ) }
小提醒
还有个细节:你的自定义组件<lightningTalkRender/>首字母是小写的,React规定自定义组件必须首字母大写(否则会被当成普通HTML标签处理),记得改成<LightningTalkRender/>哦,不然可能会出现渲染问题。
内容的提问来源于stack exchange,提问作者hillybob991
相关产品推荐
相关产品推荐

