Redux Thunk Utils
05/30/2019This is a piece of code that was usefull for me while I was using redux and redux-thunk@1.x Some people found it usefull when I showed, so I am sharing it here.
It is basically a shortcut for writing actions and async api api requests/actions.
// Action shortcut
export function makeActionCreator(type, ...argNames) {
let action = function (...args) {
let action = { type }
argNames.forEach((arg, index) => {
action[argNames[index]] = args[index]
})
return action
}
return {
action,
type,
}
}
// Usage
export const ENTER_CHAT_ROOM = makeActionCreator("ENTER_CHAT_ROOM", "room")
With our action generator utility, we further extend it for redux-thunk usage.
A common pattern arised most of the times I used thunk, so I abstracted it into a function. This way I had to write less code, but if needed the action could be further extended by chaining 'thens' and 'catchs' on the returning promise.
export function asyncCreator(api, actionName, resourceName) {
let actionNames = ["REQUEST", "SUCCESS", "FAILURE"].map(
stage => actionName + "_" + stage
)
let request = makeActionCreator(actionNames[0], "parameters").action
let success = makeActionCreator(actionNames[1], resourceName).action
let failure = makeActionCreator(actionNames[2], "error").action
let action = function (...parameters) {
return function (dispatch) {
dispatch(request(...parameters))
return api(...parameters)
.then(function (response) {
dispatch(success(response.data))
})
.catch(function (error) {
dispatch(failure(error))
throw error
})
}
}
return {
REQUEST: actionNames[0],
SUCCESS: actionNames[1],
FAILURE: actionNames[2],
request,
success,
failure,
action,
}
}
// actions.js - Usage
const fetchUsersApi = fetch("/users")
export const fetchUsers = asyncCreator(fetchUsersApi, "FETCH_USERS", "users")
// reducer.js
import { combineReducers } from "redux"
import fetchUsers from "./actions"
function loading(state = false, action) {
switch (action.type) {
case fetchUsers.REQUEST:
return true
case fetchUsers.SUCCESS:
case fetchUsers.FAILURE:
return false
default:
return state
}
}
function error(state = "", action) {
switch (action.type) {
case fetchUsers.FAILURE:
return action.error
default:
return state
}
}
function users(state = [], action) {
switch (action.type) {
case fetchUsers.SUCCESS:
return action.users
default:
return state
}
}
export default combineReducers({
loading,
error,
users,
})
These helper functions made my life with redux and redux-thunk much easier as long declaration files became short one.
Hope this can also help you out!