Skip to content

Instantly share code, notes, and snippets.

@disintegrator
Last active November 10, 2015 04:01
Show Gist options
  • Save disintegrator/01d8ca10775007e16838 to your computer and use it in GitHub Desktop.
Save disintegrator/01d8ca10775007e16838 to your computer and use it in GitHub Desktop.
Redux async action helpers
import * as ra from 'redux-actions'
export const {createAction} = ra
export function createAsyncAction(name, worker) {
const request = `${name}_REQUEST`
const success = `${name}_SUCCESS`
const fail = `${name}_FAIL`
const stages = {
request: createAction(request),
success: createAction(success),
failed: createAction(fail),
}
return {
[request]: stages.request,
[success]: stages.success,
[fail]: stages.failed,
[name]: worker.bind(stages),
}
}
export function createAsyncHandlers(name, {request, failed, success}) {
return {
[`${name}_REQUEST`]: (state, action) => {
let next = state
.set('loading', state.get('loading', Set()).add(name))
.set('errors', state.get('errors', Map()).remove(name))
if (request) { next = request(next, action) }
return next
},
[`${name}_FAILED`]: (state, action) => {
let next = state
.set('loading', state.get('loading', Set()).remove(name))
.set('errors', state.get('errors', Map()).set(name, action.payload))
if (failed) { next = failed(next, action) }
return next
},
[`${name}_SUCCESS`]: (state, action) => {
let next = state
.set('loading', state.get('loading', Set()).remove(name))
.set('errors', state.get('errors', Map()).remove(name))
if (success) { next = success(next, action) }
return next
}
}
}
import React from 'react'
import {connect} from 'react-redux'
@connect(
(state) => ({
loading: state.get('loading').has('FETCH_USER'),
user: state.get('user')
})
)
export default class extends React.Component {
}
import {createAsyncAction} from './actionhelpers'
export createAsyncAction('FETCH_USER', function(uid) {
return (dispatch) => {
dispatch(this.request())
return fetch('/api/events')
.catch((err) => {
dispatch(ERROR(err))
dispatch(this.failed(err))
throw err
})
.then((res) => {
dispatch(this.success(res))
return res
})
}
})
import {handleActions} from 'redux-actions'
import {Map, Set} from 'immutable'
import {createAsyncHandlers} from './actionhelpers'
const initalState = Map({
loading: Set(),
errors: Map()
})
const FETCH_USER = createAsyncHandlers('FETCH_USER', {
success(state, action) {
return state.set('user', action.payload)
}
})
export default handleActions({
...FETCH_USER
}, initialState)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment