Skip to content

Instantly share code, notes, and snippets.

@traverse
Forked from minheq/meta_pattern.md
Created May 7, 2018 06:58
Show Gist options
  • Save traverse/d254bc5a1f36de8ef50729c9c46e0dcf to your computer and use it in GitHub Desktop.
Save traverse/d254bc5a1f36de8ef50729c9c46e0dcf to your computer and use it in GitHub Desktop.
Using Meta Pattern to reduce redux boilerplate

Meta Pattern

When developing with Redux, often times we spend time on a lot of boilerplate code, and some common logic tend to become repeated. We can use Meta pattern to avoid code repetition while still taking advantage of Redux features. It is a simple concept and works like this:

In actions we define the actual type in meta property with name and type fields instead of type property. So a action looks like so:

{
  meta: {
    // Use logic/flow of this action
    type: STATIC_TYPE_NAME
    // Name of the field in the reducer so we can obtain/preserve the state of the action
    name: IDENTIFIER
  }
  // Usually it is a combination of STATIC_TYPE_NAME and IDENTIFIER for DevTools/verbosity purposes only
  type: DYNAMIC_TYPE_NAME
}

For example, we have a some logic to call API that requests for exchange rate and user profile. It would be cumbersome to write REQUEST_INIT, REQUEST_SUCCESS, REQUEST_FAILURE everytime we have a distinct API call. Normally, it would look something like this:

For some API call to get exchange rate
  // create exchangeRateReducer (INIT, SUCCESS, FAILURE)
  // create exchangeRateActions (INIT, SUCCESS, FAILURE)
  // create exchangeRateActionsCreators (INIT, SUCCESS, FAILURE)
For some API call to get user profile
  // create userReducer (INIT, SUCCESS, FAILURE)
  // create userActions (INIT, SUCCESS, FAILURE)
  // create userActionsCreators (INIT, SUCCESS, FAILURE)

... tens of other API calls with same structure

Instead, by applying meta pattern we can do this:

Initialize apiRequester reducer/actions/action creators
  // create apiRequesterReducer (INIT, SUCCESS, FAILURE)
  // create apiRequesterActions (INIT, SUCCESS, FAILURE)
  // create apiRequesterActionsCreators (INIT, SUCCESS, FAILURE)

And so then we can reuse the logic by dispatching these actions:

// Dispatch action to get exchange rate

{
  meta: {
    type: REQUEST_INIT
    name: EXCHANGE_RATE
  }
  type: EXCHANGE_RATE_REQUEST_INIT // Auto generated
}

// Dispatch action to get user profile

{
  meta: {
    type: REQUEST_INIT
    name: USER_PROFILE
  }
  type: USER_PROFILE_REQUEST_INIT // Auto generated
}

Then if we want to do something after the API calls were successful, using redux-saga or some listener we can do this:

take(USER_PROFILE_REQUEST_INIT, doSomethingWithProfileSaga)
take(EXCHANGE_RATE_REQUEST_INIT, doSomethingWithExchangeRateSaga)

Benefits are two-folds:

  1. We can reuse the reducer/action/saga logic
  2. In DevTools we get to see the action type with name of the request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment