Nickel Plated Moose

    redux-api-middleman-formdata-fix

    0.0.8 • Public • Published

    Build Status npm version

    Redux API Middleman

    A Redux middleware extracting the asynchronous behavior of sending API requests.

    Usage:

    Get Started:

    • Create the middleware and put into your middleware chain:
    import { createStore, applyMiddleware } from 'redux'
    import createApiMiddleman from 'redux-api-middleman'
     
    let apiMiddleware = createApiMiddleman({
      baseUrl: 'http://api.myapp.com',
    })
     
    const store = applyMiddleware(
      [ apiMiddleware ]
    )(createStore)()
    • Use it in your action creators:
    // user action
     
    import { CALL_API } from 'redux-api-middleman'
     
    export const GETTING_MY_INFO = 'GETTING_MY_INFO'
    export const GET_MY_INFO_SUCCESS = 'GET_MY_INFO_SUCCESS'
    export const GET_MY_INFO_FAILED = 'GET_MY_INFO_FAILED'
     
    export function getMyInfo() {
      return {
        [CALL_API]: {
          method: 'get',
          path: '/me',
          sendingType: GETTING_MY_INFO,
          successType: GET_CONTRACTS_SUCCESS,
          errorType: GET_MY_INFO_FAILED
        }
      }
    }
    • Handle it in your reducer:
    // user reducer
     
    import { GET_CONTRACTS_SUCCESS } from 'actions/users'
     
    const defaultState = {}
     
    export default function(state = defaultState, action) {
      switch(action.type) {
        case GET_CONTRACTS_SUCCESS:
          return action.response
        default:
          return state
      }
    }
     

    The code above would send a GET request to http://api.myapp.com/me, when success, it would dispatch an action:

    {
      type: GET_CONTRACTS_SUCCESS,
      response: { the-camelized-response-body }
    }

    Features:

    • Async to Sync: Abstract the async nature of sending API to make it easier to implement/test
    • Universal Rendering Friendly
    • Support chaining(successive) API calls
    • Side Effect Friendly
    • Replay request optionally when failed
    • Tweek request/response format when needed

    API Documentation:

    Creation:

    A middleware can be created like this:

    import apiMiddleware from 'redux-api-middleman'
     
    apiMiddleware({
      baseUrl: 'https://api.myapp.com',
      errorInterceptor: ({ err, proceedError, replay, getState })=> {
        // handle replay here
      },
      generateDefaultParams: ({ getState })=> {
        return {
          headers: { 'X-Requested-From': 'my-killer-app' },
        }
      },
      maxReplayTimes: 5
    })

    Options:

    baseUrl: The base url of api calls(required)

    errorInterceptor(optional):

    When provided, this function would be invoked whenever an API call fails. The function signature looks like this:

    ({ err, proceedError, replay, getState })=> {
     
    }

    Where:

    err is the error object returned by superagent, replay() can be used to replay the request with the same method/parameters, proceedError() can be used to proceed error to reducers

    For example, to refresh access token when server responds 401:

    ({ err, proceedError, replay, getState })=> {
      if(err.status === 401) {
        refreshAccessToken().then((res)=> {
           // here you can pass additional headers if you want
           let headers = {
             'x-access-token': res.token,
           }
           replay({ headers })
         })
      } else {
        proceedError()
      }
    }

    The code above would do the token refreshing whenever err is 401, and proceed the original error otherwise.

    generateDefaultParams(optional):

    A function which takes ({ getState }) and returns an object like this:

    {
      headers: { 'x-header-key': 'header-val' },
      query: { queryKey: 'query-val' },
      body: { bodyKey: 'body-val' }
    }

    On each request, the object returned by this function would be merged into the request's header, query, and body, respectively.


    Usage In Action Creators:

    In Action Creators, we can use the following code to send a single request:

    import { CALL_API } from 'redux-api-middleman'
     
    export const ON_REQUEST_SUCCESS = 'ON_REQUEST_SUCCESS'
    export const ON_REQUEST_FAILED = 'ON_REQUEST_FAILED'
    export const ON_SENDING_REQUEST = 'ON_SENDING_REQUEST'
     
    export function getInfo({ username }) {
      return {
        extraKey: 'extra-val',
     
        [CALL_API]: {
          method: 'get',
          path: `/users/${username}/info`,
          successType: ON_REQUEST_SUCCESS,
          errorType: ON_REQUEST_FAILED,
          sendingType: ON_REQUEST_FAILED,
          afterSuccess: ({ getState, dispatch, response }) => {
            //...
          },
          afterError: ({ getState, error })=> {
            //...
          }
        }
      }
    }

    In short, just return an action object with CALL_API.

    Options:

    method(required):

    Http verb to use, can be get, post, put or del

    path(optional):

    Request path to be concated with baseUrl

    url:

    Full url of request, will take precedence over path and will ignore baseUrl

    camelizeResponse(optional):

    Camelize response keys of the request. default to true

    Transform { user_name: 'name' } to { userName: 'name' }

    decamelizeRequest(optional):

    Decamelize request payload keys. default to true

    Transform { userName: 'name' } to { user_name: 'name' }

    withCredentials(optional):

    Enable Access-Control requests or not. default to true

    sendingType(optional):

    Action type to be dispatched immediately after sending the request

    successType(required):

    Action type to be dispatched after the API call success

    errorType(optional):

    Action type to be dispatched after the API call fails

    afterSuccess(optional):

    A callback function to be invoked after dispatching the action with type successType. ({ getState, dispatch, response }) would be passed into this callback function. This is a good place to handle request-related side effects such as route pushing.

    afterError(optional):

    A callback function to be invoked after dispatching the action with type errorType. ({ getState, error }) would be passed into this callback function.

    Sending Chaining Requests:

    To send chaining requests, just return an action with CHAIN_API-keyed object like this:

    import { CALL_API, CHAIN_API } from 'redux-api-middleman'
     
    export const ON_REQUEST_SUCCESS1 = 'ON_REQUEST_SUCCESS1'
    export const ON_REQUEST_SUCCESS2 = 'ON_REQUEST_SUCCESS2'
     
    export function getInfo({ username }) {
      return {
        [CHAIN_API]: [
          ()=> {
            return {
              extraKey: 'extra-val',
              [CALL_API]: {
                method: 'get',
                path: `/users/${username}/info`,
                successType: ON_REQUEST_SUCCESS1
              }
            }
          },
          (responseOfFirstReq)=> {
            return {
              [CALL_API]: {
                method: 'get',
                path: `/blogs/${responseOfFirstReq.blogId}`,
                successType: ON_REQUEST_SUCCESS2
              }
            }
          }
        ]
      }
    }

    In the code above, we send an API to /users/${username}/info to fetch user info containing a key blogId. After the first request is finished, we then send the second request with the blogId returned by server.


    Usage In Reducers:

    During the life cycle of an API call, several types of actions would be dispatched:

    sendingType action:

    After the request has been sent, an action of type sendingType would be dispatched immediately. The action would contain the key-val pairs other than CALL_API in the action object.

    For example, if our action object looks like this:

    {
      extraKey1: 'extra-val-1',
      extraKey2: 'extra-val-2',
      [CALL_API]: {
        ...
      }
    }

    then the sendingType action would be:

    {
      type: sendingType,
      extraKey1: 'extra-val-1',
      extraKey2: 'extra-val-2'
    }

    successType action:

    After the server responds successfully, an action of type successType would be dispatched. The action would contain:

    • the key-val pairs other than CALL_API in the action object
    • an extra response key, with its value be the server response

    For example, if the server responds with a body like this:

    {
      responseKey: 'response-val'
    }

    then the successType action would be:

    {
      type: successType,
      extraKey1: 'extra-val-1',
      extraKey2: 'extra-val-2',
      response: {
        responseKey: 'response-val'
      }
    }

    errorType action:

    After the server responds fails, an action of type errorType would be dispatched. The action would contain:

    • the key-val pairs other than CALL_API in the action object
    • an extra error key, with its value be the error object returned by axios

    LICENCE:

    MIT

    Keywords

    none

    Install

    npm i redux-api-middleman-formdata-fix

    DownloadsWeekly Downloads

    5

    Version

    0.0.8

    License

    ISC

    Unpacked Size

    396 kB

    Total Files

    12

    Last publish

    Collaborators

    • chiunhau