一直以来,rxjs 和 react 都不太搭,要在 React 中使用 rxjs 往往需要写并不怎么优雅的代码,比如:
class Example extends React.Component {
constructor(props) {
super(props);
const initial = -1;
this.state = {
value: initial,
};
this.subscription = null;
}
componentDidMount() {
this.register();
}
componentDidUpdate(prevProps) {
if (prevProps.value$ !== this.props.value$) {
this.unregister();
this.register();
}
}
componentWillUnmount() {
this.unregister();
}
register() {
this.subscription = this.props.value$
.subscribe((value) => {
this.setState({ value });
});
}
unregister() {
if (this.subscription) this.subscription.unsubscribe();
}
render() {
const { value } = this.state;
return (
<div>{value}</div>
)
}
}
ReactDOM.render(<Example value$={interval(1000)} />, document.body);
上面这段代码,会根据 value$
这个 Observable 的数据,通过 React State 这个桥梁,去更新 UI。并且,代码考虑到了给定的 value$
可能后续变化的情况。如果不考虑后续 props
的修改,上面的代码依然需要在 componentDidMount
的时候注册回调并更新,然后在 componentWillUnmount
的时候注销,显得非常的啰嗦。
LeetCode 提供的 rxjs-hooks 提供了一个更为优雅的解决方案:
const Example = (props) => {
const initial = -1;
const value = useObservable(
(inputs$) => inputs$.pipe(
switchMap(([value$]) => value$),
),
initial,
[props.value$]
);
return (<div>{value}</div>);
};
ReactDOM.render(<Example value$={interval(1000)} />, document.body);
rxjs-hooks 另外提供了 useEventCallback
来更好的处理事件流,具体可以查看官方的文档。