RX + React setState - 避免“在现有状态转换期间无法更新”?

时间:2017-11-22 22:04:51

标签: reactjs rxjs observable

问题

public componentDidMount() { 

    // after component mounts I want to get updates from RX source
    const that = this;
    SomeExternalObservable.subscribe((value) => {
        that.setState((prev, props) => ({
            currentValue: value
        });
    });

}

在某些情况下,我会收到警告Cannot update during an existing state transition” React with Observable

我检查了SO以获取该问题的答案,但大多数人建议将我的代码移至componentDidMount

这里会发生什么

使用https://github.com/jayphelps/react-observable-subscribe等库时也会出现问题。

2 个答案:

答案 0 :(得分:1)

  

我发布了答案,因为它似乎允许,支持   这里   https://meta.stackexchange.com/questions/17463/can-i-answer-my-own-questions-even-if-i-knew-the-answer-before-asking;   花了一些时间来找到问题,并且找不到类似的SO帖子,   所以我希望它会帮助别人。

<强>解决方案

因为我们无法期望异步触发订阅工作解决方案是强制它,即使用调度程序:

public componentDidMount() { 

    // after component mounts I want to get updates from RX source
    const that = this;
    SomeExternalObservable
        .subscribeOn(Scheduler.asap) // here
        .subscribe((value) => {
            that.setState((prev, props) => ({
                currentValue: value
            });
        });

}

<强>为什么

总结问题

是否有React point of view right way来解决该问题,与提出的解决方案不同?

答案 1 :(得分:1)

另一种方法是使用props而不是setState。

为了使用Rx管理React状态,我更喜欢使用mapPropsStream重构帮助器。如果您不倾向于使用HOCs,可能会有点混乱,但实际上非常简单。

const withSomeExternalValue = mapPropsStream(props$ =>
    Observable.combineLatest(
        props$,
        someExternal$.startWith(null),
        (props, someExternalValue) => ({...props, someExternalValue})
    )
);

const MyEnhancedComponent = withSomeExternalValue(MyComponent);

MyEnhancedComponent 是一种新的组件类型。当它将挂载时,它也将订阅外部Observable。任何发射的值都将使用新值将组件呈现为prop。

其他说明和注释

  • props $ 是一个Observable of props。任何支柱的更改都会导致为 prop $

  • 发出新项目
  • 返回的Observable是一个新的道具Observable,它的发射项目将用于渲染增强的组件。

  • .startWith(null),是为了确保在发出 someExternal $ 的第一个值之前呈现增强的组件。在这种情况下, someExternalValue 道具将以null开头

  • withSomeExternalValue 如果其他组件需要这些外部值,则可以重复使用HOC。 withSomeExternalValue(MyAnotherComponent)

  • mapPropsStream可以与其他Observable实现一起使用 - 因此应该进行配置。以下是如何将它与Rx -

  • 一起使用

可以全局配置:

import rxjsconfig from 'recompose/rxjsObservableConfig'
setObservableConfig(rxjsconfig)

或者使用mapPropsStreamWithConfig

import rxjsConfig from 'recompose/rxjsObservableConfig'
const mapPropsStream = mapPropsStreamWithConfig(rxjsConfig)