RxJS + React 结合使用时,我们经常会遇到 “setState called on an unmounted component” 错误。这个错误的原因是,当使用 RxJS 发出一个请求时,在得到回应之前组件已经被卸载了,而我们又在卸载后的组件上调用了 setState() 方法。这样会导致 React 抛出一个错误。
那么如何解决这个问题呢?下面我们提供几种解决方案。
解决方案一:使用 takeUntil 操作符
使用 takeUntil 操作符可以用来取消掉我们之前发送的请求,从而避免发生上述错误。我们可以在 componentWillUnmount 中通过 unsubscribe 取消我们的请求。示例如下:
-- -------------------- ---- ------- ------ ------ - --------- - ---- -------- ------ - ------- - ---- ------- ------ - --------- - ---- ----------------- ----- --- ------- --------- - ------------------ - ------------- ---------- - - ----- ----- -- ----------------- - --- ---------- - ------------------- - ------------------ --------- -- ----------- ----------------------------------- --------------- -- - --------------- ---- --- --- - ---------------------- - ------------------------- ----------------------------- - -------- - ----- - ---- - - ----------- ------ ---------- - ------------ - -------------------- - -
在上面的代码中,我们使用了 takeUntil 操作符取消掉之前发送的请求。在 componentWillUnmount 中,我们首先调用 this.unsubscribe$.next() 来关闭订阅,接着调用 this.unsubscribe$.complete() 来完成 Observable,然后再调用 setState() 方法,这样就避免了上述错误的发生。
解决方案二:使用 switchMap 操作符
我们还可以使用 switchMap 操作符来解决这个问题,示例如下:
-- -------------------- ---- ------- ------ ------ - --------- - ---- -------- ------ - --------- - ---- ------- ------ - --------- - ---- ----------------- ----- --- ------- --------- - ------------------ - ------------- ---------- - - ----- ----- -- - ------------------- - ------------------- ------------ ------------------ -- -------------------- --------------- -- - --------------- ---- --- --- - ---------------------- - ------------------------- ----------------------------- - -------- - ----- - ---- - - ----------- ------ ---------- - ------------ - -------------------- - -
在上面的代码中,我们使用了 switchMap 操作符来解决这个问题。在 componentDidMount 中,我们监听了 document 的 mousemove 事件,并通过 switchMap 这个操作符切换 Observable 对象。当有新的 mousemove 事件触发时,我们就发送了一个新的请求。这样即使组件被卸载了,我们也不会发送不必要的请求,从而避免了上述错误的发生。
总结
RxJS 是一个强大的库,可以用于处理复杂的异步事件。但是在使用 RxJS 和 React 结合时,我们需要小心处理组件的生命周期和状态。对于 “setState called on an unmounted component” 错误,我们可以选择使用 takeUntil 或 switchMap 操作符来取消之前发送的请求,从而避免发生错误。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64facf37f6b2d6eab319b48d