更好用的 RxJS+React hooks 集成方案。以及一些好用的工具函数!
https://zhuanlan.zhihu.com/p/92248348
在 @little-saga/rx-hooks,Novel 是一种满足特定接口的函数。开发者将自定义的逻辑封装为相应的 novel,然后调用 useMemoNovel 函数,使 novel 运行在一个 React 组件的生命周期内(基于 React hooks 机制)。
Novel 内的逻辑一般采用 RxJS 编程,@little-saga/rx-hooks 不对 novel 内部的逻辑进行限制,开发者可以选用自己熟悉的 RxJS 开发方式。而 Novel 的输入/输出(即函数的参数和返回值)则需要满足下面描述的要求。
type Novel<I, S extends object, D extends object, E> = (
input$: Observable<I>,
state$: Observable<S>,
) =>
| Observable<S>
| {
nextState?: Observable<S>
derived?: Observable<D>
exports?: E
teardown?(): void
}
- novel 函数的参数用来抽象
React -> RxJS
的通信过程 - novel 函数被调用时,调用参数为
input$
和state$
- input$ 表示 React 当前向 novel 提供的输入,其类型为
BehaviorSubject<I>
- 每次组件的 render 方法被执行时,input$ 中就会发出组件最新提供的值;值对应于
useMemoNovel(input, initState, novel)
中的 input 参数 - 「input$ 之于 novel」相当于「props 之于 React 组件」;input$ 应当被认为是只读的
- state$ 表示 novel 绑定到 React 组件的当前状态;其背后对应一个 useState hook
- 每次组件的 render 方法被执行时,novel 就可以通过 state$ 获取到最新的状态
- input$ 表示 React 当前向 novel 提供的输入,其类型为
- novel 函数的返回值用来抽象
RxJS -> React
的通信过程 - novel 的返回值一般为一个对象,对象中各个字段的含义如下
- nextState:用于表示下一个状态的 Observable. 每当该 Observable 发出一个值的时候,对应的 useState hook 的 setState 方法将被调用,组件将重新渲染
- derived: 用于表示缓存/计算状态的 Observable. useMemoNovel 的返回值中会包含该 Observable 的最新的值;该 Observable 发出值的时候不会触发渲染
- exports: 对象导出,使得 React 组件可以获取到 novel 内部的对象
- teardown: 清理逻辑,当组件被卸载时,该函数将被调用
- novel 的返回值也可以是一个简单的 Observable,此时该 Observable 的作用与 nextState 字段相同。
泛型参数说明:
I
input 参数的类型S
state 参数的类型D
novel 返回值中 derived 字段的类型E
novel 返回值中 exports 字段的类型
useMemoNovel 将在一个 React 组件内执行 novel 函数,并将 novel 的输入输出与 React 组件绑定起来。注意 useMemoNovel 是一个 React hooks,调用该函数需要遵循 hooks rules.
useMemoNovel 会返回一个数组,数组的长度固定为 2,第一个元素是 state 与 derived 两个对象的合并结果,第二个元素即为 novel 返回对象的 exports 字段。
和 useMemoNovel
相似,但是 novel 函数会在 useEffect 会被调用