All Projects → jfairbank → redux-resource

jfairbank / redux-resource

Licence: MIT license
Redux action creator for managing RESTful resources

Programming Languages

javascript
184084 projects - #8 most used programming language
HTML
75241 projects

redux-resource

Circle CI

Easily create actions for managing server resources like fetching, creating, or updating. Provide action types used in your reducer function for updating your redux store based on results from the server.

** DEPRECATED **

This package is no longer maintained. The redux-resource package name will be given to a different team managing a similar type of package for managing remote resources in Redux. More info to come soon.

Install

$ npm install redux-resource

Usage

Use createResourceAction to create an action for fetching a resource. Supply a URL (with optional path parameter placeholders) along with three action types to represent the act of sending the request, receiving a successful response from the server, and receiving an error from the server. Make sure to use these action types in your reducer function!

import { createResourceAction } from 'redux-resource';

const fetchTodo = createResourceAction(
  '/todos/:id', 'FETCH_TODO', 'RCV_TODO', 'ERR_RCV_TODO'
);

When calling the action, pass in any parameters to fill in the placeholders or add additional search query parameters.

// make request to '/todos/42'
store.dispatch(fetchTodo({ id: 42 }));

// make request to '/todos/42?extraParam=hi'
store.dispatch(fetchTodo({
  id: 1,
  extraParam: 'hi'
}));

createResourceAction defaults to GET requests. To use other verbs swap out the URL string with an object literal that defines the URL and HTTP verb.

const addTodo = createResourceAction(
  { url: '/todos/add', method: 'POST' },
  'ADD_TODO', 'ADDED_TODO', 'ERR_ADDING_TODO'
);

You can also supply headers inside the object literal. This is useful if your request content type needs to be something other than application/json.

const resource = {
  url: '/todos/add',
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  }
};

const addTodoFromForm = createResourceAction(
  resource, 'ADD_TODO', 'ADDED_TODO', 'ERR_ADDING_TODO'
);

In addition to taking parameters, the action can take request data. You can pass in null for params if you don't have any.

// make request to '/todos/add' with JSON '{"title":"Finish tests"}'
store.dispatch(
  addTodo(null, { title: 'Finish tests' })
);

// make request to '/todos/add' with form data 'title="Add%20more%20features"'
store.dispatch(
  addTodoFromForm(null, { title: 'Add more features' })
);

Actions return a thunk (an anonymous function). To use the actions with your store you must include the middleware. (redux-resource uses redux-thunk under the hood.)

// configureStore.js

import { applyMiddleware, createStore } from 'redux';
import { resourceMiddleware } from 'redux-resource';
import myReducer from './myReducer';

const createStoreWithMiddleWare = applyMiddleware(resourceMiddleware)(createStore);
const store = createStoreWithMiddleWare(myReducer);

Make sure to add the action types to your reducer function!

function reducer(state = INITIAL_STATE, action) {
  switch(action.type) {
    case 'FETCH_TODO':
      // ...

    case 'RCV_TODO':
      return { ...state, todo: action.payload };

    case 'ADD_TODO':
      // ...

    case 'ERR_ADDING_TODO':
      return { ...state, error: action.payload };

    // etc.

    default:
      return state;
  }
}

Dispatching the actions will return a promise that resolves when a request succeeds or fails. Therefore, catch won't work on failed requests. Your reducer should manage how your state reacts to failed requests. This allows you to gracefully handle state changes from errors for React applications for example.

// Successful request
store.dispatch(fetchTodo({ id: 42 })).then(() => {
  const todo = store.getState().todo;
});

// Failing request
store.dispatch(addTodo(null, { title: 'Finish tests' })).then(() => {
  const error = store.getState().error;
});

API

createResourceAction

createResourceAction(
  url: string | {
    url: string,
    [method: string],
    [headers: Object]
  },
  sendType: string,
  successType: string,
  errorType: string
)

url - URL for resource. Allows path parameter placeholders like /users/:id.

sendType - The action type when dispatching the request.

successType - The action type when successfully receiving back the resource from the server.

errorType - The action type when a server request fails.

Example

import { applyMiddleware, createStore } from 'redux';
import { resourceMiddleware, createResourceAction } from 'redux-resource';

const createStoreWithMiddleWare = applyMiddleware(resourceMiddleware)(createStore);

const INITIAL_STATE = {
  fetching: false,
  user: null,
  error: null
};

function reducer(state = INITIAL_STATE, action) {
  switch(action.type) {
    case 'FETCH_USER':
      return { ...state, fetching: true };

    case 'RECEIVE_USER':
      return { ...state, fetching: false, user: action.payload };

    case 'ERR_RECEIVE_USER':
      return { ...state, fetching: false, error: action.payload };

    default:
      return state;
  }
}

const store = createStoreWithMiddleWare(reducer);

const fetchUser = createResourceAction(
  '/users/:id', 'FETCH_USER', 'RECEIVE_USER', 'ERR_RECEIVE_USER'
);

store.dispatch(fetchUser({ id: 1 }))
  .then(() => console.log(store.getState()));

// {
//   fetching: false,
//   user: { id: 1, name: 'Jeremy' },
//   error: null
// }
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].