ReactJS状态未更新在setState回调中

时间:2017-03-03 03:11:23

标签: javascript reactjs ecmascript-6 state immutable.js

我正在构建一个SIP电话,当前的调用由SipPhone类处理,并使用React显示在前端。 SipPhone有一个调用列表,用于触发React组件正在侦听的回调。

主要电话组件的初始状态包含空Immutable List

calls

每当SipPhone更新时,此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列表,而在其他时间tick不会更改。当我在设置状态之前记录列表时,它应该是应该的,但是当登录setState回调时,它与之前的状态保持不变。有时候它会起作用,有时却不起作用。

为了进一步测试这个,我添加了一个状态变量 2017-03-02 22:00:18.797 ERROR 13736 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.orm.jpa.JpaSystemException: could not deserialize; nested exception is org.hibernate.type.SerializationException: could not deserialize] with root cause java.io.StreamCorruptedException: invalid stream header: 20323031 ,每次我在这里设置状态时它都会递增。此更改准确地反映在回调中,而呼叫列表保持不变。

我似乎无法弄清楚为什么会这样做。我实际上是使用普通数组而不是不可变列表开始这个项目,并遇到了同样的问题。我一直在使用React已经有一段时间了,从来没有遇到过这个问题......有什么想法吗?

3 个答案:

答案 0 :(得分:4)

事实证明,我的代码中的另一个函数是在某些情况下在调用componentWillUpdate之前设置状态,导致它忽略对setState的初始调用。这是错误的来源。

答案 1 :(得分:0)

我们之前遇到过这个问题,当时我们使用的是Immutable(而不是普通的JS)

四处搜索,在反应文档中看到了这个文档片段

  

setState()不会立即改变this.state,但会创建挂起状态转换。在调用此方法后访问this.state可能会返回现有值。

     

无法保证对setState的调用进行同步操作,并且可以对调用进行批处理以获得性能提升。

除非使用setState的回调功能,否则我建议您选择componentDidUpdate

答案 2 :(得分:0)

由于太多的方法和嵌套的回调,我个人发现JsSIP库非常复杂。这与您在React应用程序中通常使用的内容非常不同。我的朋友和我曾经创建了一个名为<SipProvider/>的简单组件,它将所有JsSIP复杂性抽象出去,让我们通过配置道具和使用上下文方法来调用。我们终于在npm上发布了这个软件包 - 随时也可以从中受益! https://www.npmjs.com/package/react-sip

如果您想在应用程序的状态中存储一些数据但又不想使用redux / mobx / apollo客户端,那么名为recompose的库可能会有所帮助。它允许您将状态提升为更高阶的组件,从而将状态逻辑与其表示分开。我在一些项目中一直使用withState() / withReducer(),我很难想象再次使用this.setState()