tappleby / redux-batched-subscribe

store enhancer for https://github.com/reactjs/redux which allows batching subscribe notifications.
MIT License
504 stars 32 forks source link

Example: Selective batching based on meta.batch in Action #24

Open davidjbradshaw opened 6 years ago

davidjbradshaw commented 6 years ago

Following on from the examples of @staab and @peteruithoven. Here is an example that selectively batches actions using requestAnimationFrame, based on the presence of meta.batch in an action. It uses a middleware to inspect actions and call notify().

This allows the batching, for example async actions, whilst letting everything else work as normal.

You can replace rafUpdateBatcher() with LoDash's debounce() if you prefer.

batching/state.js

export default {
  notify: null
}

batching/enhancer.js

import { batchedSubscribe } from 'redux-batched-subscribe'
import State from './state'

export default batchedSubscribe(
  (freshNotify) => {
    State.notify = freshNotify
  }
)

batching/rafUpdateBatcher.js

import raf from 'raf'
import State from './state'

let rafID

function delayedNotify () {
  rafID = null
  State.notify()
}

export default function rafUpdateBatcher () {
  if (rafID) return // prevent multiple request animation frame callbacks
  rafID = raf(delayedNotify)
}

batching/middleware.js

import rafUpdateBatcher from 'rafUpdateBatcher'
import State from './state'

const shouldBatch = action => action.meta && action.meta.batch

export default () => next => (action) => {
  const resolved = next(action)

  if (State.notify && !shouldBatch(action)) {
    State.notify()
  } else {
    rafUpdateBatcher()
  }

  return resolved
}

store.js

import { applyMiddleware, compose, createStore } from 'redux'
import batchedSubscribeMiddleware from './batching/middleware'
import batchedSubscribeEnhancer from './batching/enhancer'

const store = createStore(
  reducer,
  intialState,
  compose(
    batchedSubscribeEnhancer,
    applyMiddleware(batchedSubscribeMiddleware)
  )
)

Example action

{
   type: ACTION,
   payload: { ... },
   meta: { batch: true }
}
Mamoru1234 commented 6 years ago

@davidjbradshaw Thank you for your example it was extremely useful to me. Maybe it makes sense to post somewhere(for example on wiki) and refer it in REAME, what do you think?

davidjbradshaw commented 6 years ago

I'm happy if @tappleby would like to do that.