Skip to content

Latest commit

 

History

History
126 lines (87 loc) · 3.69 KB

46.精读《react-rxjs》.md

File metadata and controls

126 lines (87 loc) · 3.69 KB

46.精读《react-rxjs》.md

React-rxjs 给出一个新思路让 rxjs 更好与 react 结合

概述

  • 链接 View 与 Store 层,无感 rxjs

    import { inject } from 'react-rxjs'
    import store$, { inc, dec } from './store'
    import MyComponent from './view'
    
    const props = (storeState: number): MyProps => {
      number: storeState,
        inc,
        dec
    }
    export default inject(store$, props)(MyComponent)
    • storeState 是 store 的全部数据(react-rxjs 是多 store 思想,所以 inject 第一个参数传入不同的 store,组件会与对应的 store 绑定)
  • store 层必须将 rxjs 与 action 对接

    import { createStore } from 'react-rxjs'
    
    const inc$ = new Subject<void>()
    const des$ = new Subject<void>()
    
    const reducer$: Observable<(state: number) => number> = Observable.merge(
    	inc$.map(() => (state:number) => state + 1)
      dec$.map(() => (state: number) => state - 1)
    )
    const store$ = createStore("example", reducer$, 0)
    
    export inc = () => inc$.next()
    export dec = () => dec$.next()
    export default store$

聚焦 Action 关注数据源

const inc$ = new Subject<void>()
export inc = () => inc$.next()
  • Rxjs 两种代码组织方式

    • 数据源的抽象、聚合
    • 对已经聚合过的单一数据源订阅后进行处理,处理过程只包含对本数据源的操作,不再进行 merge 其他数据
  • rxjs 的优势:抽象(副作用隔离),以及强大的流处理能力

  • Action 部分没有足够的抽象能力就无法进行流的 merge,如果生成实例自己就是一个事件触发器,想要进行流合并,就必须在 reducer 中执行

    const incReducer = inc$.merge(requestUser$).map(() => (state: number) => state + 1)
  • React-rxjs 的形式解决了 rxjs 与 react 结合繁琐的问题,如果按照规范,Action 的功能比较弱,无法进行下一步抽象

redux-observable

// 单一数据源下载dispatch过程触发事件进入action,每个action都源自同一数据源订阅,通过action.type筛选确保执行正确的action
const pingEpic = action$ =>
	actions$.filter(action => action.type === 'PING')
		.delay(1000) // Asychronously wait 1000ms then continue
		.mapTo({type: 'PONG'})
// later...
dispatch({type: 'PING'})

// reducer中心化处理做过滤
const pingReducer = (state = { isPinging: false }, action) => {
  switch(action.type) {
    case 'PING':
      	return { isPinging: true };
      
    case 'PONG':
      	return { isPinging: false };
    default:
      	return state;
  }
}
  • 比上优势是:

    第一部分是数据源的抽象、聚合,第二部分是对已经聚合过的单一数据源订阅后进行处理,这里处理过程只包含对本数据源的操作,不能 merge 其他数据源

  • 比下缺点:

    redux-observable 的样板代码只会比 react-redux 多,投入使用的话较好的方式是按照 dva 的思路,减少 redux-observable 的样板代码

summary

  • 最后可以围观一下 cyclejs,虽然此库脱离了 react 生态,但是他可以解决 react+rxjs 的循环依赖(A 依赖 B, B 依赖 A)的问题:视图的回调函数可以产生数据源

    function main(sources) {
      const input$ = sources.DOM.select('.field').events('input')
      const name$ = input$.map(ev => ev.target.value).startWith('')
      
      const vdom$ = name$.map(name =>
      	div([
        label('Name:')
        input('.field', {attrs: {type: 'text'}})
      	hr()
      	h1('Hello' + name),
      ])                    
    	)
      
      return { DOM: vdom$ }
    }
  • rxjs 还是难以落地到 react 业务代码中,本质上没有 cyclejs 这种机制解决数据源引起的循环依赖的问题