ReactJS 状态未更新在 setState 回调中
Posted
技术标签:
【中文标题】ReactJS 状态未更新在 setState 回调中【英文标题】:ReactJS state not updated In setState callback 【发布时间】:2017-07-23 00:52:33 【问题描述】:我目前正在构建一个 SIP 电话,当前呼叫由 SipPhone 类处理,并使用 React 显示在前端。 SipPhone 有一个调用列表,这些调用会触发 React 组件正在监听的回调。
主电话组件的初始状态包含一个空的Immutable List:
constructor(props)
super(props);
...
this.state =
calls: List(),
;
每当 SipPhone 更新时,此 calls
列表会通过回调触发的事件进行更新。
handleUpdate = ( calls ) =>
const nextCalls = List(calls.map(call =>
return new Call( ... ) // Call is an Immutable Record
);
console.log(nextCalls.toJS()); // This prints the new list I want to save
this.setState( calls: nextCalls , () =>
console.log(this.state.calls.toJS()); // The list is empty here
);
有时它会成功更新calls
列表,而有时calls
不会改变。当我在设置状态之前记录列表时,它应该是,但是当登录 setState 回调时,它与之前的状态保持不变。有时有效,有时无效。
为了进一步测试这一点,我添加了一个状态变量tick
,每次我在这里设置状态时都会递增。这种变化准确地反映在回调中,而调用列表保持不变。
我似乎无法弄清楚它为什么会这样做。实际上,我使用普通数组而不是不可变列表开始了这个项目,并遇到了同样的问题。我使用 React 已经有一段时间了,从来没有遇到过这个问题……有什么想法吗?
【问题讨论】:
您能否发布完整的代码示例,例如调用第二个代码块的位置? 我添加了更多细节——不幸的是,在这种情况下很难给出完整的代码示例,因为它是一个相当大的项目。 算了,我一时误会了。 @RyanMcClure 嗨..我根据您的示例创建了一个fiddle,它运行良好。唯一显着的区别是我使用了handleUpdate(calls)
而不是handleUpdate = ( calls )
。你能看看吗?参数中是否需要那些完美的大括号??
@RyanMcClure 解决了您的问题吗?
【参考方案1】:
事实证明,在某些情况下,我的代码中的另一个函数在调用 componentWillUpdate 之前设置了状态,导致它忽略了对 setState 的初始调用。这是错误的根源。
【讨论】:
【参考方案2】:我个人发现 JsSIP 库非常复杂,因为方法和嵌套回调太多。这与您通常在 React 应用程序中使用的非常不同。我和我的朋友曾经创建了一个名为<SipProvider/>
的简单组件,它将所有 JsSIP 复杂性抽象出来,让我们通过配置 props 和使用上下文方法来进行调用。我们终于在 npm 上发布了这个包 - 也可以随时从中受益!https://www.npmjs.com/package/react-sip
如果您想在应用程序的状态中存储一些数据,但又不想打扰 redux / mobx / apollo 客户端,那么一个名为 recompose
的库可能会有所帮助。它使您可以将状态提升为更高阶的组件,从而将状态逻辑与其表示分离。我在几个项目中一直在使用withState()
/ withReducer()
,我很难想象再次使用this.setState()
!
【讨论】:
【参考方案3】:我们之前遇到过这个问题,当我们使用 Immutable(而不是普通的 JS)时
四处挖掘,在 react docs 中发现了这个文档 sn-p
setState() 不会立即改变 this.state 而是创建一个挂起的状态转换。调用此方法后访问 this.state 可能会返回现有值。
不保证 setState 调用的同步操作,并且调用可能会被批处理以提高性能。
除非真的强制使用setState
的回调函数,否则我建议使用componentDidUpdate
。
【讨论】:
所以据我了解,新状态应该始终反映在回调中,因为它是在完成后调用的。但是在我的情况下,新状态实际上根本没有更新。在渲染函数中记录列表会显示未更改的列表。以上是关于ReactJS 状态未更新在 setState 回调中的主要内容,如果未能解决你的问题,请参考以下文章
ReactJS TypeError:无法读取未定义的属性“setState”[重复]
ReactJS:警告:setState(...):在现有状态转换期间无法更新
ReactJs:获取无法读取未定义错误的属性“setState”[重复]