问题
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等库时也会出现问题。
答案 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
});
});
}
<强>为什么强>
componentDidMount
在渲染后直接发生,并且更改为状态将导致额外渲染 - 这可能发生在相同的刻度线中(https://reactjs.org/docs/react-component.html#componentdidmount)setState
应该异步工作,但不是必须的; React将在运行时(https://reactjs.org/docs/react-component.html#setstate)总结问题
是否有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)
import rxjsConfig from 'recompose/rxjsObservableConfig'
const mapPropsStream = mapPropsStreamWithConfig(rxjsConfig)