rxjs and hooks

JavaScript

一直以来,rxjsreact 都不太搭,要在 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 来更好的处理事件流,具体可以查看官方的文档