Redux Thunk Utils

30 mai 2019 Última atualização: 2 jul 2021

Atenção: este texto é de 2019 e seu conteúdo está desatualizado. Ele é mantido aqui como referência histórica.

Traduzido do en usando google translate

Este é um pedaço de código que foi útil para mim enquanto eu estava usando redux e redux-thunk@1.x Algumas pessoas acharam útil quando eu mostrei, então estou compartilhando aqui.

É basicamente um atalho para escrever ações e solicitações / ações de API assíncronas.

// 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")

Com nosso utilitário gerador de ação, nós o estendemos ainda mais para uso redux-thunk.

Um padrão comum surgiu na maioria das vezes em que usei thunk, então eu o abstraí em uma função. Dessa forma, eu tive que escrever menos código, mas se necessário, a ação poderia ser estendido ainda mais pelo encadeamento de 'então' e 'pega' na promessa de retorno.

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,
})

Essas funções auxiliares tornaram minha vida com redux e redux-thunk muito mais fácil, arquivos de declaração longos tornaram-se curtos.

Espero que isso também possa ajudá-lo!