coeus-redux
TypeScript icon, indicating that this package has built-in type declarations

1.1.0 • Public • Published

Fork from redux to support promise in reducers and subscribers.

Build Status npm version npm downloads

Diff

  1. Rewrite 'dispatch' in createStore.js and 'combineReducers' in combineReducers.js, which makes store.dispatch() and reducers generated from combineReducers() always return a promise. In addition, subscribers can return a promise now because they has been wrapped by promise.all() in store.dispatch(). If you want to guarantee the sequence of actions, use promise.then() to chain every dispatching carefully. As all exceptions will be catched in promise, feel free to call promise.catch() rather than wrap store.dispatch() in a 'try catch' block.

  2. Seperate 'dispatch({ type: ActionTypes.INIT })' from 'createStore' and 'replaceReducer' in createStore.js to make it a new function named 'initState' for the store object. Everything will be fine as long as you add it right behind 'createStore' and 'replaceReducer'.

Examples

const store = createStore((state = [], action) => {
  switch (action.type) {
    case 'ADD_TODO':
      return new Promise(function (resolve) {
        setTimeout(function () {
          resolve([
            ...state, 
            {
              id: id(state),
              text: action.text
            }
          ])
        })
      })
    default:
      return state
  }
})
 
return store.initState().then(() => {
  expect(store.getState()).toEqual([ ])
 
  return store.dispatch({ type: 'ADD_TODO', text: 'Hello' })
}).then(() => {
  expect(store.getState()).toEqual([
    {
      id: 1,
      text: 'Hello'
    }
  ])
  
  store.replaceReducer((state = [], action) => {
    return state
  })
  
  return store.initState()
}).then(() => {
  expect(store.getState()).toEqual([
    {
      id: 1,
      text: 'Hello'
    }
  ])
  
  return store.dispatch({ type: 'ADD_TODO', text: 'World' })
}).then(() => {
  expect(store.getState()).toEqual([
    {
      id: 1,
      text: 'Hello'
    }
  ])
})
const store = createStore(reducers.todos)
 
let unsub
return store.initState().then(() => {
  unsub = store.subscribe(() => {
    expect(store.getState()).toEqual([
      {
        id: 1,
        text: 'Hello'
      }
    ])
 
    unsub()
 
    return store.dispatch(addTodo('World')).then(() => {
      expect(store.getState()).toEqual([
        {
          id: 1,
          text: 'Hello'
        },
        {
          id: 2,
          text: 'World'
        }
      ])
 
      return store.dispatch(addTodo('Redux'))
    })
  })
 
  return store.dispatch(addTodo('Hello'))
}).then(() => {
  expect(store.getState()).toEqual([
    {
      id: 1,
      text: 'Hello'
    },
    {
      id: 2,
      text: 'World'
    },
    {
      id: 3,
      text: 'Redux'
    }
  ])
})
const reducer = combineReducers({
  counter: (state = 0, action) => new Promise(function (resolve) {
    setTimeout(function () {
      resolve(action.type === 'increment' ? state + 1 : state)
    })
  }),
  stack: (state = [], action) => new Promise(function (resolve) {
    setTimeout(function () {
      resolve(action.type === 'push' ? [ ...state, action.value ] : state)
    })
  })
})
 
return reducer({}, { type: 'increment' }).then((s1) => {
  expect(s1).toEqual({ counter: 1, stack: [] })
 
  return reducer(s1, { type: 'push', value: 'a' })
}).then((s2) => {
  expect(s2).toEqual({ counter: 1, stack: [ 'a' ] })
})

More examples? It might be helpful to look at the test cases which have been rewritten.

License

MIT

Package Sidebar

Install

npm i coeus-redux

Homepage

redux.js.org

Weekly Downloads

1

Version

1.1.0

License

MIT

Last publish

Collaborators

  • chieveit