npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

redux-rest-api

v1.0.1

Published

Middleware that gives you a uniform way to define API actions in Redux applications.

Downloads

13

Readme

redux-rest-api Build Status

Middleware that gives you a uniform way to define API actions in Redux applications.

Example usage:

import { API_ACTION_TYPE } from 'redux-rest-api'

store.dispatch({
  [API_ACTION_TYPE]: {
    types: ['PENDING', 'SUCCESS', 'FAILURE'],
    endpoint: 'https://monsterfactory.net',
    fetchOptions: {
      headers: {
        'Content-Type': 'application/json'
      },
      method: 'POST',
      body: JSON.stringify({
        name: 'Guy Fieri'
      })
    }
  }
}).then(() => {
  console.log()('Oh no what have you done')
}).catch(() => {
  console.log('Thank god')
})

Installation

npm install redux-rest-api

Usage

Add middleware to store

In order for a fetch to request to be generated whenever an API action is dispatched, the api middleware must be applied to your store.

// Adding the api middleware to your store
import { apiMiddleware } from 'redux-rest-api'
import { applyMiddleware, createStore } from 'redux'

const middleware = applyMiddleware(apiMiddleware)

const store = createStore(reducers, initialState, middleware)

Now whenever an API action like this gets dispatched to the store:

// Example API action
import { API_ACTION_TYPE } from 'redux-rest-api'

const promise = store.dispatch({
  [API_ACTION_TYPE]: {
    types: ['PENDING', 'SUCCESS', 'FAILURE'],
    endpoint: 'https://monsterfactory.net',
    fetchOptions: { /* Options to pass to underlying fetch request */ }
  }
})

// Do something with the returned Promise if you want to, but you don't have to.

A fetch request will be made to the given endpoint, and three actions with the specified types will be dispatched while that fetch request is being made. The

You can specify the types of these three actions by setting the types property of the api action to an array of three strings.

The first string will be the pending action type, the second the success action type, and the third the failure action type.

Pending Action

The pending action is dispatched to the store before the fetch request is created.

// Pending action
{
  type: ['PENDING']
}

Success action

This action will be dispatched to the store if the fetch request resolves with an OK status code. The action's payload will contain the JSON response from the endpoint.

// Success action
{
  type: ['SUCCESS'],
  payload: { /* Server response as JSON */ }
}

Failure action

The failure action is dispatched to the store if the fetch request is rejected with a non-OK status code. The payload of the action will contain the Response object from the rejected request.

// Failure action
{
  type: ['FAILURE'],
  payload: { /* Response object */ }
}

Hook up a reducer (or write your own)

Now that you have middleware that is generating actions for you, you need to create a reducer that will handle those actions and update the store accordingly.

You can use the reducer included with redux-rest-api to handle these actions, or you can write your own.

Using the provided reducer

Odds are the state for most of your API requests is going to look very similar:

// Example API request state
const state = {
  // True if a request is in progress
  isPending: false,

  // Contains a response from an API if a request was successful.
  response: null,

  // Contains the failed [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) object from a rejected request.
  error: null
}

As such, redux-rest-api provides a reducer that you can use to manage the state of multiple API requests.

Example usage
// Setting up reducers to handle the state for multiple API requests within an application
import { configureApiReducer } from 'redux-rest-api'
import { combineReducers } from 'redux'

const reducers = combineReducers({
  // Create a reducer that will respond to API actions with the specified `types`.
  monsters: configureApiReducer({
    // The types for this API action.
    types: ['MONSTERS_FETCH_PENDING', 'MONSTERS_FETCH_SUCCESS', 'MONSTERS_FETCH_FAILURE']
  }),
  pokemon: configureApiReducer({
    // The types for this API action.
    types: ['POKEMON_FETCH_PENDING', 'POKEMON_FETCH_SUCCESS', 'POKEMON_FETCH_FAILURE']
  }),
  ...
})

export reducers

The initial state of the store will look like this:

// Initial state
{
  monsters: {
    isPending: false,
    response: null,
    error: null
  },
  pokemon: {
    isPending: false,
    response: null,
    error: null
  }
}
How the reducer updates state

The api reducer will handle actions from the API middleware that match the given types.

Pending action type

The reducer will set the isPending property to true.

// State after receiving a pending action
{
  isPending: false => true
}
Success action type

The api reducer will set the isPending property to false and will populate the response field with the JSON response from the API. error will be set to null.

// State after receiving a success action
{
  isPending: true => false,
  response: null => { /* JSON response */ },
  error: { /* Previous error object */ } => null
}
Failure action type

The api reducer will set the isPending property to false and will populate the error field with the Response object from the failed fetch request.

// State after receiving a failure action
{
  isPending: true => false,
  error: null => { /* Response object from failed fetch request */ }
}

Using your own reducer

If the provided reducer doesn't meet your needs, you can always write your own reducer to handle the actions that are dispatched by the API middleware.

Check out the source for the included reducer for an example.

Dispatching API actions

Once you have a reducer to handle the actions dispatched by the API middleware, you can start dispatching API actions.

API actions have the following properties:

types

This is an array of three strings that define the action types that will be dispatched by the API middleware.

endpoint

The url for the fetch request.

fetchOptions

An object containing the options that will be passed to the underlying fetch request, such as body and method.

For a full list of options you can pass to the fetch request, check out out the MDN docs.

Because the API middleware converts API actions to Promises, you can delay rendering a component until the data that it requires has been fetched. This is super handy for server side rendering.

Here's an example of delaying rendering with React Router:

// Example of delaying rendering until data has been fetched
import { API_ACTION_TYPE } from 'redux-rest-api'

// Route configuration that has been given access to the store.
// Example: routeConfig(store): route configuration
<Route path="/" component={SomeComponent} onEnter={(state, replace, next) => {
  // Dispatch an action and wait for it to resolve (or be rejected) before rendering.
  store.dispatch({
    [API_ACTION_TYPE]: {
      types: ['FIERI_DESTROY_PENDING', 'FIERI_DESTROY_SUCCESS', 'FIERI_DESTROY_FAILURE'],
      endpoint: 'http://monsterfactory.net/1',
      fetchOptions: {
        method: 'DELETE'
      }
    }
  }).then(() => {
    // Store state has been updated 🎉, render the component
    next()
  }).catch(() => {
    // Uh oh, something broke :/, maybe dispatch an action to render an alert?
    next()
  })
}} />

For more details on async routes in React Router, check out the React Router docs.

License

MIT