# Home

[![Travis build status](http://img.shields.io/travis/jamesplease/redux-resource.svg?style=flat)](https://travis-ci.org/jamesplease/redux-resource) [![npm version](https://img.shields.io/npm/v/redux-resource.svg)](https://www.npmjs.com/package/redux-resource) [![npm downloads](https://img.shields.io/npm/dm/redux-resource.svg)](https://www.npmjs.com/package/redux-resource) [![Test Coverage](https://coveralls.io/repos/github/jamesplease/redux-resource/badge.svg?branch=master)](https://coveralls.io/github/jamesplease/redux-resource?branch=master) [![gzip size](http://img.badgesize.io/https://unpkg.com/redux-resource/dist/redux-resource.min.js?compression=gzip)](https://unpkg.com/redux-resource/dist/redux-resource.min.js)

A tiny but powerful system for managing 'resources': data that is persisted to remote servers.

✓ Removes nearly all boilerplate code for remotely-stored data\
✓ Incrementally adoptable\
✓ Encourages best practices like [normalized state](http://redux.js.org/docs/recipes/reducers/NormalizingStateShape.html)\
✓ Works well with APIs that adhere to standardized formats, such as JSON API\
✓ Works well with APIs that don't adhere to standardized formats, too\
✓ Integrates well with your favorite technologies: HTTP, gRPC, normalizr, redux-observable, redux-saga, and more\
✓ Microscopic file size (3kb gzipped!)

## Older Documentation

This website is for the v3.0.0 version of Redux Resource. The documentation for older versions are hosted elsewhere:

* [**v2.4.1**](https://jamesplease.github.io/redux-resource-2.4.1-docs/)

> Migration guides to the latest version can be found [**here**](https://redux-resource.js.org/other-guides/migration-guides.html).

## Installation

To install the latest version:

```
npm install --save redux-resource
```

## Table of Contents

* [**Quick Start**](/#quick-start)

  The quick start guide is a quick overview of basic Redux Resource usage.
* [**Introduction**](/introduction)

  The introduction explains why this library exists, and also explores alternative solutions.
* [**Resources**](/resources)

  This section of the guides cover resource data, resource metadata, and resource lists.
* [**Requests**](/requests)

  Requests represent asynchronous updates to resources. Learn more about them here.
* [**Other Guides**](/other-guides)

  These guides cover additional topics related to using React Request.
* [**Recipes**](/recipes)

  Recipes are recommended patterns and best practices that you can use in your application.
* [**Ecosystem Extras**](/extras)

  Redux Resource provides officially maintained bits of code that make working with the library even better.
* [**FAQ**](/faq)

  Answers to frequently asked questions.
* [**API Reference**](/api-reference)

  Describes the API of all of the exports of Redux Resource.

## Quick Start

Follow this guide to get a taste of what it's like to work with Redux Resource.

First, we set up our store with a "resource reducer," which is a reducer that manages the state for one type of resource. In this guide, our reducer will handle the data for our "books" resource.

```javascript
import { createStore, combineReducers } from 'redux';
import { resourceReducer } from 'redux-resource';

const reducer = combineReducers({
  books: resourceReducer('books')
});

const store = createStore(reducer);
```

Once we have a store, we can start dispatching actions to it. In this example, we initiate a request to read a book with an ID of 24, then follow it up with an action representing success. There are two actions, because requests usually occur over a network, and therefore take time to complete.

```javascript
import { actionTypes } from 'redux-resource';
import store from './store';

// This action represents beginning the request to read a book with ID of 24. This
// could represent the start of an HTTP request, for instance.
store.dispatch({
  type: actionTypes.READ_RESOURCES_PENDING,
  resourceType: 'books',
  resources: [24]
});

// Later, when the request succeeds, we dispatch the success action.
store.dispatch({
  type: actionTypes.READ_RESOURCES_SUCCEEDED,
  resourceType: 'books',
  // The `resources` list here is usually the response from an API call
  resources: [{
    id: 24,
    title: 'My Name is Red',
    releaseYear: 1998,
    author: 'Orhan Pamuk'
  }]
});
```

Later, in your view layer, you can access information about the status of this request. When it succeeds, accessing the returned book is straightforward.

```javascript
import { getStatus } from 'redux-resource';
import store from './store';

const state = store.getState();
// The second argument to this method is a path into the state tree. This method
// protects you from needing to check for undefined values.
const readStatus = getStatus(store, 'books.meta[24].readStatus');

if (readStatus.pending) {
  console.log('The request is in flight.');
}

else if (readStatus.failed) {
  console.log('The request failed.');
}

else if (readStatus.succeeded) {
  const book = state.books.resources[24];

  console.log('The book was retrieved successfully, and here is the data:', book);
}
```

This is just a small sample of what it's like working with Redux Resource.

For a real-life webapp example that uses many more CRUD operations, check out the [**zero-boilerplate-redux webapp ⇗**](https://github.com/jamesplease/zero-boilerplate-redux). This example project uses [React](https://facebook.github.io/react/), although Redux Resource works well with any view layer.

## Contributors

([Emoji key](https://github.com/kentcdodds/all-contributors#emoji-key))

| <p><a href="http://www.jmeas.com"><img src="https://avatars3.githubusercontent.com/u/2322305?v=4" alt=""><br><strong>James, please</strong></a><br><a href="https://github.com/jamesplease/redux-resource/commits?author=jamesplease">💻</a> <a href="/pages/-LAMPabUvROq_jbViX_T#plugin-jamesplease">🔌</a> <a href="https://github.com/jamesplease/redux-resource/commits?author=jamesplease">📖</a> <a href="/pages/-LAMPabUvROq_jbViX_T#ideas-jamesplease">🤔</a></p> | <p><a href="http://www.stephenrivasjr.com"><img src="https://avatars3.githubusercontent.com/u/682566?v=4" alt=""><br><strong>Stephen Rivas JR</strong></a><br><a href="https://github.com/jamesplease/redux-resource/commits?author=sprjr">💻</a> <a href="https://github.com/jamesplease/redux-resource/commits?author=sprjr">📖</a> <a href="/pages/-LAMPabUvROq_jbViX_T#ideas-sprjr">🤔</a> <a href="/pages/-LAMPabUvROq_jbViX_T#plugin-sprjr">🔌</a></p> |                  <p><a href="https://github.com/ianmstew"><img src="https://avatars0.githubusercontent.com/u/4119765?v=4" alt=""><br><strong>Ian Stewart</strong></a><br><a href="/pages/-LAMPabUvROq_jbViX_T#ideas-ianmstew">🤔</a></p>                 |         <p><a href="http://tbranyen.com/"><img src="https://avatars3.githubusercontent.com/u/181635?v=4" alt=""><br><strong>Tim Branyen</strong></a><br><a href="/pages/-LAMPabUvROq_jbViX_T#ideas-tbranyen">🤔</a></p>        |         <p><a href="https://github.com/jasonLaster"><img src="https://avatars1.githubusercontent.com/u/254562?v=4" alt=""><br><strong>Jason Laster</strong></a><br><a href="/pages/-LAMPabUvROq_jbViX_T#ideas-jasonLaster">🤔</a></p>         |          <p><a href="https://github.com/marlonpp"><img src="https://avatars2.githubusercontent.com/u/1104846?v=4" alt=""><br><strong>marlonpp</strong></a><br><a href="/pages/-LAMPabUvROq_jbViX_T#ideas-marlonpp">🤔</a></p>          |          <p><a href="https://github.com/JPorry"><img src="https://avatars1.githubusercontent.com/u/4296756?v=4" alt=""><br><strong>Javier Porrero</strong></a><br><a href="/pages/-LAMPabUvROq_jbViX_T#ideas-JPorry">🤔</a></p>          |
| :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
|                                                                                                   <p><a href="https://github.com/smaifullerton-wk"><img src="https://avatars2.githubusercontent.com/u/25591356?v=4" alt=""><br><strong>Smai Fullerton</strong></a><br><a href="https://github.com/jamesplease/redux-resource/commits?author=smaifullerton-wk">📖</a></p>                                                                                                  |                                                                                                                       <p><a href="https://github.com/vinodkl"><img src="https://avatars3.githubusercontent.com/u/276971?v=4" alt=""><br><strong>vinodkl</strong></a><br><a href="/pages/-LAMPabUvROq_jbViX_T#ideas-vinodkl">🤔</a></p>                                                                                                                       | <p><a href="https://github.com/ericvaladas"><img src="https://avatars3.githubusercontent.com/u/828125?v=4" alt=""><br><strong>Eric Valadas</strong></a><br><a href="https://github.com/jamesplease/redux-resource/commits?author=ericvaladas">📖</a></p> | <p><a href="http://blog.jeremyfairbank.com"><img src="https://avatars0.githubusercontent.com/u/195580?v=4" alt=""><br><strong>Jeremy Fairbank</strong></a><br><a href="/pages/-LAMPabUvROq_jbViX_T#infra-jfairbank">🚇</a></p> | <p><a href="https://www.yihangho.com"><img src="https://avatars1.githubusercontent.com/u/4226956?v=4" alt=""><br><strong>Yihang Ho</strong></a><br><a href="https://github.com/jamesplease/redux-resource/commits?author=yihangho">💻</a></p> | <p><a href="https://github.com/brycereynolds"><img src="https://avatars2.githubusercontent.com/u/1026002?v=4" alt=""><br><strong>Bryce Reynolds</strong></a><br><a href="/pages/-LAMPabUvROq_jbViX_T#example-brycereynolds">💡</a></p> | <p><a href="http://bencreasy.com"><img src="https://avatars1.githubusercontent.com/u/5614134?v=4" alt=""><br><strong>Ben Creasy</strong></a><br><a href="https://github.com/jamesplease/redux-resource/commits?author=jcrben">📖</a></p> |
|                                                                   <p><a href="http://www.guillaume-jasmin.fr"><img src="https://avatars3.githubusercontent.com/u/3513444?v=4" alt=""><br><strong>Guillaume Jasmin</strong></a><br><a href="https://github.com/jamesplease/redux-resource/commits?author=GuillaumeJasmin">💻</a> <a href="/pages/-LAMPabUvROq_jbViX_T#plugin-GuillaumeJasmin">🔌</a></p>                                                                   |                                                                                                                                                                                                                                                                                                                                                                                                                                                              |                                                                                                                                                                                                                                                          |                                                                                                                                                                                                                                |                                                                                                                                                                                                                                               |                                                                                                                                                                                                                                        |                                                                                                                                                                                                                                          |

This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind are welcome!


# Introduction

* [Motivation](/introduction/motivation)
* [Core Concepts](/introduction/core-concepts)
* [Similar Projects](/introduction/similar-projects)
* [Examples](/introduction/examples)


# Motivation

Many applications work with state that is persisted to a server. Because communicating with remote servers requires sending messages over a network, reading and writing this state does not happen instantly. The requests take time, and they may sometimes fail.

These network requests are often made as a result of a user's action within the application. It's a developer's responsibility to provide feedback to the user about these requests. When using Redux, this means writing reducers that change your store's state tree based on the status of these requests. If your application has many resources, you can run into problems when you write these reducers by hand.

For one, simply figuring out what information needs to be tracked can be difficult to figure out. Request tracking is a complicated problem.

When you do figure out something that works, it may be implemented slightly differently for different resources in your state tree. This inconsistency will propagate to your view layer. Code bases that are not consistent are more difficult to maintain.

Additionally, tracking all of this data for every request requires writing a lot of reducer code. You may omit writing some of that code to save on time. This contributes to inconsistency, and also gives you, the developer, less information to use when providing feedback to users.

Redux Resource is intended to solve these problems. It provides a system of organizing information about request state in a consistent way. It also comes with reducers that keep track of as much information as possible about every request made to remote servers, so that you don't have to.

Use Redux Resource to have more time to build great interfaces, rather than writing boilerplate Redux code.


# Core Concepts

Redux Resource has two concepts: "Resources" and "Requests."

## Resources

A resource is an object of data that you interact with in your applications. Typically, applications will have resources of several different "types." For instance, if your web application manages a public library, then you might have two resource types: "books" and "members."

Each individual resource has a unique ID, which differentiates it from other resources of the same type. Resources typically have other attributes, too. Here's an example book resource:

```javascript
{
  id: '1312',
  title: 'The Hobbit',
  releaseYear: 1937,
  author: 'J.R.R. Tolkien'
}
```

In Redux Resource, each resource type will be kept in its own [slice](http://redux.js.org/docs/recipes/reducers/UsingCombineReducers.html) of your store.

The slices contain not just the "raw" resource data, but also other information that help you to manage and organize the data on the client.

There are five pieces within a resource slice:

* `resourceType`: The resource type (such as "books" or "authors")
* `resources`: Where the resource's primary attributes are located
* `meta`: Additional information about individual resources. You can store information

  here that isn't persisted to a remote server.
* `lists`: A place to store and manage ordered arrays of resources.
* `requests`: Information about the requests that are modifying this resource type (requests

  will be covered in greater detail in the "Requests" section of these guides)

An empty resource slice looks like the following:

```javascript
// "books" resource slice
{
  resourceType: 'books',
  resources: {},
  meta: {},
  lists: {},
  requests: {}
}
```

### Resources

In the `resources` section of the slice, each key of the object is the resource's ID. This looks like the following:

```javascript
// "books" resource type slice
{
  resourceType: 'books',
  resources: {
    24: {
      // Attributes of book 24
    },
    100: {
      // Attributes of book 100
    }
  },
  meta: {},
  lists: {},
  requests: {}
}
```

This structure makes it convenient to quickly access a resource's attributes if you know its ID.

### Resource Metadata

Typically, client-side applications need to store additional information about resources, such as if the resource has been "selected" by a user, or maybe information about the resource that has been input into a form.

Resource metadata is for this purpose. It's any information that is **not** persisted to a remote server.

In Redux Resource, all metadata is stored on an object. This meta object, like the resources object, has resource IDs as its keys, and has values that are metadata. An example is:

```javascript
// "books" resource type slice
{
  resourceType: 'books',
  resources: {},
  meta: {
    24: {
      // Metadata for book 24
    },
    100: {
      // Metadata for book 100
    }
  },
  lists: {},
  requests: {}
}
```

### Resource Lists

Often, applications need to keep track of ordered groupings of resources. For instance, has a user selected certain books on the interface? Or did you fetch a user's recent book purchases from a server, sorted by purchase date?

In Redux Resource, both of these situations can be handled using resource lists.

Lists in your store are an array of resource IDs. A resource's lists might look like the following:

```javascript
{
  resourceType: 'books',
  resources: {},
  meta: {},
  lists: {
    searchResults: [10, 233, 4, 50],
    shoppingCart: [10, 409],
  },
  requests: {}
}
```

Redux Resource provides Redux actions for you to create, update, and delete lists.

### Requests

The last section of the resource slice is called `requests`. This is an object where each key is maps to a request object, described below.

## Requests

Request objects represent network requests, such as HTTP requests. Like resources, they are stored in the store.

Typically, requests are HTTP requests, but they can represent anything that is asynchronous. The primary characteristic of requests is that they do not occur instantly. They take time to complete, and they don't always succeed.

In Redux Resource, this characteristic of requests is represented as one of four "statuses":

* `IDLE`: the request hasn't begun yet
* `PENDING`: the request has started, but has not yet finished
* `FAILED`: the request was unsuccessful
* `SUCCEEDED`: the request was successful

In addition to having a status, a request keeps track of the resources it operated upon.

Requests in Redux Resource are associated with a resource type, which is the primary resource type that is being affected by the request. Accordingly, the requests can be found within that resource's slice, under the `requests` key.

Within `requests`, each key is a "request key," which is a string used to identify that request. A request with the key `"readFavoriteBooks"` would be stored like the following:

```javascript
{
  resourceType: 'books',
  resources: {},
  meta: {},
  lists: {},
  requests: {
    readFavoriteBooks: {
      requestKey: 'readFavoriteBooks',
      status: 'SUCCEEDED',
      // The resources that were affected by this crud action
      ids: [24, 10, 50]
    }
  }
}
```

## Conclusion

When you use Redux Resource, information about **every** CRUD operation that you make in your application is stored in your application's state tree.

By storing this information at such a granular level, Redux Resource provides a robust foundation from which you can build truly great user experiences. And you avoid writing a substantial amount of boilerplate code.


# Similar Projects

This isn't the only library that aims to reduce boilerplate when it comes to managing resources. Below is a brief comparison between this library and a selection of others. Keep in mind that you're reading this comparison on the Redux Resource documentation site, so it may be biased.

## [redux-rest-resource](https://github.com/mgcrea/redux-rest-resource)

redux-rest-resource does not track metadata on a per-resource basis. Instead, it merges all metadata for all resources onto a single property.

Consider, for instance, if a user decides to save two resources simultaneously. Redux Resource will track those two actions independently, but redux-rest-resource will only track that at least one resource is being saved.

## [redux-resources](https://github.com/travisbloom/redux-resources)

A short list of things that redux-resources does differently from this library is:

1. resources are split up in the store based on the requests that you make.

   Redux Resource stores all resources of the same type into one object,

   and provides request lists to organize your resources by requests.
2. it does not provide metadata on a per-resource level
3. it provides timestamps for the operations that you perform out of the box
4. it keeps a cache of errors returned from the server out of the box

The features of redux-resources that are not included in Redux Resource would be straightforward to add in via [plugins](/other-guides/custom-action-types). However, getting the level of detail that Redux Resource provides for requests appears like it would be difficult to achieve using redux-resources.

## [redux-json-api](https://github.com/dixieio/redux-json-api)

redux-json-api provides less detail about individual resource's metadata than Redux Resource: it stores a single number that counts the number of concurrent requests of the same type that are in flight, whereas Redux Resource tracks all requests separately.

In addition, redux-json-api requires that your backend adhere to [JSON API](http://jsonapi.org/). Although Redux Resource does not provide a complete integration with JSON API out of the box, the plugin system would enable you to add more features such as relationship support.


# Examples

A number of examples are distributed with the library's [source code](https://github.com/jamesplease/redux-resource).

## Read Resource

To run this example:

```
git clone https://github.com/jamesplease/redux-resource.git

cd redux-resource/examples/read-resource
npm install
npm start

open http://localhost:3000/
```

This example shows what the most basic usage of Redux Resource looks like. Two differences between a real-world application and this example are:

* A real-world application would likely use the performant [React Redux](https://github.com/reactjs/react-redux) bindings for re-rendering.
* A real-world application would likely use [`combineReducers`](http://redux.js.org/docs/api/combineReducers.html) so that it could have multiple resources in its state tree.

## Lists and Named Requests

To run this example:

```
git clone https://github.com/jamesplease/redux-resource.git

cd redux-resource/examples/lists-and-named-requests
npm install
npm start

open http://localhost:3000/
```

This example shows how you can use request objects to track requests that don't target a specific resource ID. It also shows you how lists can be used to display two different ordered subsets of the same type of resource.

In this example, a user's owned books are fetched, then displayed in a list on the interface. At the same time, a list of recently released books are also fetched, and displayed in another list in the interface.

A real-world application would likely use the performant [React Redux](https://github.com/reactjs/react-redux) bindings for re-rendering.

## "Real World" Examples

This is a list of open-source projects that are using Redux Resource.

* [Chronos Timetracker](https://github.com/web-pal/chronos-timetracker): A desktop client for JIRA.
* [Zero boilerplate redux](https://github.com/jamesplease/zero-boilerplate-redux): A simple recreation of the GitHub Gists webapp.

> Do you have an open source project that uses Redux Resource that you would like to add to the list? Open an issue or make a Pull Request!


# Resources

* [Resource Reducers](/resources/resource-reducers)
* [Resource Objects](/resources/resource-objects)
* [Meta](/resources/meta)
* [Lists](/resources/lists)
* [Modifying Resources](/resources/modifying-resources)


# Resource Reducers

The main export of Redux Resource, [`resourceReducer`](https://github.com/jamesplease/redux-resource/tree/e0d24c6c69879d54e94c1ab9976b4b6a9d5adb7f/docs/api-reference/resource-reducer.html), is a function that returns a reducer. For each resource type in your application, you should use this function to create a reducer. A resource reducer will manage all of the state for its resource type.

Creating a resource reducer is the first step to getting started with Redux Resource. If your application manages books, then you would create a reducer for the books resource like so:

```javascript
import { resourceReducer } from 'redux-resource';

const booksReducer = resourceReducer('books');
```

Once you have your resource reducers, you need to combine them into a single reducer. Users of Redux frequently use [`combineReducers`](http://redux.js.org/docs/api/combineReducers.html) for this purpose. When you use `combineReducers`, your store is divided up into slices, where each reducer that you input manages its own section of the state. These sections are often called "slices."

The rest of this documentation will frequently refer to "resource slices," which are the slices of your store that are managed by a resource reducer.

The following code snippet demonstrates how you might set this up:

```javascript
import { combineReducers } from 'redux';
import { resourceReducer } from 'redux-resource';

const reducer = combineReducers({
  books: resourceReducer('books'),
  authors: resourceReducer('authors'),
  people: resourceReducer('people'),
});
```

The `resourceReducer` function takes a second option, which can be used to configure the resource reducer. Refer to [the API documentation for `resourceReducer`](/api-reference/resource-reducer) to learn more.

> Note: keep in mind that Redux Resource works with or without `combineReducers`.


# Resource Objects

Each resource slice has a property called `resources`. All of your resource data is stored here. If your application manages books, then you may have the following resource slice:

```javascript
{
  resourceType: 'books',
  resources: {
    4: {
      title: 'Harry Potter',
      releaseYear: 1997,
      author: 'J.K. Rowling'
    },
    102: {
      title: 'The Hobbit',
      releaseYear: 1937,
      author: 'J.R.R. Tolkien'
    }
  },
  // ...a resoure slice contains other information, too. But this guide
  // will focus on the `resources` section of the slice.
}
```

The `resources` object allows you to quickly access any resource given its ID. For instance, the following code demonstrates accessing the data for the book with ID 102:

```javascript
const state = store.getState();

const book = state.books.resources[102];
```

> Note: For more advanced retrieval of resources from the store, you can use the [`getResources` method](/api-reference/get-resources).

## What is a Resource?

Resources are the individual pieces of data that come from your backend. For instance, if you're using a RESTful API, you might have an endpoint, `GET /books/24`, that returns you the information for the book with the ID 24. That information is a single resource.

The only requirement of a resource is that it **must** have an `id` property. The following are some examples of valid resources:

```javascript
{
  __typename: 'Person',
  id: 23,
  firstName: 'Bill',
  lastName: 'Graham',
  friendId: 250
}
```

```javascript
{
  id: '23',
  attributes: {
    firstName: 'Bill',
    lastName: 'Graham'
  },
  relationships: {
    friend: {
      type: 'person',
      id: 250
    }  
  }
}
```

```javascript
{
  id: '1586353b-7891-48ef-956a-07ea4d40e98f'
}
```

We understand that not all backend services return data that have an ID attribute. For such services, a transformation function will need to be written to change that data into Redux Resource-compatible resources. We understand that this isn't ideal, but we believe the benefits of Redux Resource outweigh this inconvenience.

Here are some examples of common data formats that a backend may send over, and how you can change them into Redux Resource compatible resources.

```javascript
// Backend returns:
[
 'en',
 'fr',
 'es'  
]

// Transform it like so:
[
  {
    id: 'en'
  },
  {
    id: 'fr'
  },
  {
    id: 'es'
  },
]
```

```javascript
// Backend returns:
{
 'en': 'English',
 'fr': 'French',
 'es': 'Spanish'
}

// Transform it like so:
[
  {
    id: 'en',
    displayName: 'English'
  },
  {
    id: 'fr',
    displayName: 'French'
  },
  {
    id: 'es',
    displayName: 'Spanish'
  },
]
```

```javascript
// Backend returns:
[
 {
   bookId: 23,
   title: 'The Brilliance of the Moon'
 },
 {
   bookId: 120,
   title: 'The Good Thief'
 },
 {
   bookId: 255,
   title: 'My Name is Red'
 }
]

// Transform it like so:
[
  {
    id: 23,
    title: 'The Brilliance of the Moon'
  },
  {
    id: 120,
    title: 'The Good Thief'
  },
  {
    id: 255,
    title: 'My Name is Red'
  }
]
```

## Modifying Resources

There are two ways to modify resources: synchronously and asynchronously. The guide on [modifying resources](/resources/modifying-resources) describes both of these approaches.

## Best Practices

A good rule of thumb is to treat the resource objects as the last-known source of truth from the server. In other words, don't modify the resource objects within the `resources` section of a slice unless the server tells you that they have changed.

For local changes in your application, such as form data, you should store that information somewhere else. You can store it wherever you think is best: your favorite forms library, component state, or even in the metadata section of the resource slice.

A good workflow that implements this pattern is:

1. Fetch resources from the server
2. Place them into the `resources` section of a resource slice
3. If the user can modify resources, store the user's modification information somewhere other than

   in the `resources` section of the resource slice
4. Once you persist those changes to the server, and the server responds, update

   the `resources` with the latest information from the server

Following this pattern will help keep you organized, even as your application grows.


# Meta

The `meta` section of a resource slice is structured similarly to the `resources` section: it is an object, and each of its keys is a resource ID.

You can store additional information about individual resources within `meta`. You can put anything that you would like here. Typically, the information that you store within `meta` are the things that are useful for the client-side application, but that don't need to be sent to the server.

Resource metadata is intended to solve the problem some developers encounter when they pollute server-side data with client-side data. Mixing the two can get messy. Use metadata to keep things organized.

The following example slice has some metadata, `selected`, associated with two resources. This value could represent that a user has "selected" these resources in the UI.

```javascript
{
  resourceType: 'books',
  meta: {
    4: {
      selected: true
    },
    102: {
      selected: true
    }
  },
  // ...there are other things on a resource slice, too. But this guide will
  // focus on meta.
}
```

## "CRUD" Metadata

Out of the box, Redux Resource sets some metadata on your resources for you. This metadata represents whether or not that particular resource is being created, read, updated, or deleted using a network request. The four values are:

* `createStatus`
* `readStatus`
* `updateStatus`
* `deleteStatus`

The value of each of these properties will be one of the four [request statuses](/requests/request-statuses): `IDLE`, `PENDING`, `SUCCEEDED`, or `FAILED`.

This metadata can be used to track the request status of CRUD operations against a particular resource in some situations. For more, refer to the [Tracking Request Statuses guide](/other-guides/tracking-request-statuses).

## Modifying Metadata

There are two ways to modify metadata: synchronously and asynchronously. The guide on [modifying resources](/resources/modifying-resources) describes both of these approaches.


# Lists

Applications frequently need to keep track of groupings of a resource type. That's what lists are for. A list is an array of resource IDs. You can make as many lists as you would like for each resource type.

Here are two situations when you might find lists useful:

* Keeping track of a server-side sorted array of resources
* If your UI allows user to "select" resources on your interface by clicking a

  checkbox, then you could store the "selected" IDs in a list

The above isn't meant to be exhaustive; it is simply to give you an idea of the kinds of situations where lists can be useful. Any time that you need a subsection of your resources (whether it needs to be ordered or not), you should use lists.

The following shows what two lists look like in a resource slice:

```javascript
{
  resourceType: 'books',
  lists: {
    favorites: [1, 100, 52, 1230],
    selected: [24, 13, 1]
  },
  // ...there are other things in a resource slice, as well. But this guide will
  // focus on lists.
}
```

## List Names

A good list name is short and descriptive. Here are some examples:

* mostRecent
* searchResults
* favorites
* selected

You could include the resource type in the name, too (i.e. "selectedBooks").

Sometimes, you may need to use a dynamic list name. A dynamic list name is a string that has a variable component to it, such as:

```javascript
`authorsBooks:${authorId}`
```

It is okay to use dynamic names, but keep in mind that static names are simpler to manage, so you might find them preferable to use over dynamic list names.

Sometimes, you may think that you need a dynamic list name when another approach is better.

For instance, the above list, `authorsBooks:${authorId}` may represent the list of books that were written by the author with the ID `authorId`. In this situation, you could instead store that list of IDs on the author object itself, like a [foreign key](https://en.wikipedia.org/wiki/Foreign_key) in a relational database.

This might look like:

```javascript
// An author 'resource object'
{
  id: 'a39cva22',
  name: 'Jane Austen',
  books: ['103', '10', '129903']
}
```

If the backend does not return this data with the author's primary data, then you may choose to store the list of IDs on the author's [resource metadata](/resources/meta) instead:

```javascript
// An author metadata object
{
  readStatus: 'SUCCEEDED',
  updateStatus: 'IDLE',
  createStatus: 'IDLE',
  deleteStatus: 'IDLE',
  books: ['103', '10', '129903']
}
```

## Accessing the Resources in a List

To retrieve the resources in a list, you can use [`getResources`](/api-reference/get-resources).

```javascript
import { getResources } from 'redux-resource';
import store from './my-redux-store';

const state = store.getState();
const favoriteBooks = getResources(state.books, 'favorites');
```

## Updating Lists

In the [next guide](/resources/modifying-resources), we will cover how you can modify data within a resource slice, including lists.


# Modifying Resources

There are two ways to modify resources in the store: synchronously and asynchronously. There are different action types for each approach.

If you are modifying the resource by making a network request, then you should use the asynchronous actions. If you are modifying resource information due to some local action, then you should use the synchronous actions.

## Synchronous Actions

There are two action types for modifying resources synchronously:

* `UPDATE_RESOURCES`: Create or update resources, meta, and/or lists
* `DELETE_RESOURCES`: Delete resources from the resource slice. Deleting resources also

  removes them from any lists that they are in.

One use case for the synchronous actions is for managing client-side lists of resources. If a user can select or deselect resources in your interface, then you might use `UPDATE_RESOURCES` to update the list representing their selection.

### Creating or Updating Resources

The `UPDATE_RESOURCES` action type is for updating resource information in the store. This action type allows you to update resources across multiple slices at the same time.

You can pass the following properties to this action:

* `resources`: An object of resource types to be updated. Here is an example action that updates the books and authors slices at the same time:

  ```javascript
  {
    type: actionTypes.UPDATE_RESOURCES,
    resources: {
      books: {
        24: {
          title: 'The Hobbit'
        }
      },
      authors: {
        1: {
          name: 'J.R.R. Tolkien'
        }
      }
    }
  }
  ```
* `meta`: Similar to `resources`, but for metadata instead of the primary resource attributes. This example updates the metadata for a few resources:

  ```javascript
  {
    type: actionTypes.UPDATE_RESOURCES,
    meta: {
      books: {
        24: { selected: true },
        101: { selected: true },
        150: { selected: true },
      },
      authors: {
        15: { selected: false }
      }
    }
  }
  ```
* `lists`: Adds new lists, or replaces existing lists. Note that it is not possible to specify that the lists that you pass in be merged with an existing list. This is because the list order is sometimes significant, and you are responsible for maintaining the proper order.

  ```javascript
  {
    type: actionTypes.UPDATE_RESOURCES,
    lists: {
      books: {
        selected: [1, 50, 2120]
      }
    }
  }
  ```
* `mergeResources`: When `true`, the new resources data that you pass will be shallowly merged with existing resource entries. Passing `false` will replace the existing resource with the new data that you pass. If you pass a Boolean, then it will apply to every resource slice. You can also pass an object to scope the value to a specific slice.

  Defaults to `true`.

  ```javascript
  {
    type: actionTypes.UPDATE_RESOURCES,
    mergeResources: {
      books: false
    }
    // Note: you can also pass `mergeResources: false` to apply it to every resource type.
  }
  ```
* `mergeMeta`: Like `mergeResources`, but for metadata instead.

  Defaults to `true`.

  ```javascript
  {
    type: actionTypes.UPDATE_RESOURCES,
    mergeMeta: {
      books: false
    }
    // Note: you can also pass `mergeMeta: false` to apply it to every resource type.
  }
  ```

### Deleting Resources

The `DELETE_RESOURCES` action type is used for removing resources from the store.

You can pass the following properties to this action:

* `resources`: An object of resource types. Within each type, you can specify an array of resources to delete. Here is an example action that deletes a few books:

  ```javascript
  {
    type: actionTypes.DELETE_RESOURCES,
    resources: {
      books: [1, 20, 54],
    }
  }
  ```

  * `meta`: Metadata to **add** to the resources. This can be used to store client-side

    information about the deletion.

  ```javascript
  {
    type: actionTypes.DELETE_RESOURCES,
    resources: {
      books: [1]
    },
    meta: {
      books: {
        1: {
          deletionReason: 'duplicate'
        }
      }
    }
  }
  ```

When resources are deleted, they will be removed from all of the lists in the store as well.

## Asynchronous Actions

Resources are frequently modified as a result of network requests, which are asynchronous.

With Redux Resource, these operations are represented using objects called Requests. Requests are covered in detail in the next section of these guides. If you want to read about them now, then follow [this link](/requests/request-objects).


# Requests

* [Request Objects](/requests/request-objects)
* [Keys](/requests/request-keys)
* [Names](/requests/request-names)
* [Statuses](/requests/request-statuses)
* [Request Actions](/requests/request-actions)
  * [Updating Lists](/requests/request-actions/updating-lists)
  * [Reading Resources](/requests/request-actions/reading-resources)
  * [Updating Resources](/requests/request-actions/updating-resources)
  * [Creating Resources](/requests/request-actions/creating-resources)
  * [Deleting Resources](/requests/request-actions/deleting-resources)


# Request Objects

A request object represents an asynchronous operation. Typically, they are used to represent HTTP requests, but they are designed to be generic enough for any kind of networking technology. Requests are stored in your Redux store.

Data about requests is useful for providing feedback to users of your application, such as if the operation is still in flight, if it failed, or if it succeeded.

## Location in the Store

Requests are stored on the resource slice, along with other information such `resources`, `meta`, and `lists`. Every request has a resource type associated with it, which is the resource that is primarily affected by the request. This determines which resource slice the request is stored within.

Requests, like resources, require a unique identifier. For resources, the unique identifier is the `id` property. For requests, the identifier is called a key, and it is stored on the request object under the property `requestKey`.

## Properties

A request object has the following properties:

* `requestKey`: A string that serves as an identifier for the request
* `requestName`: A human-readable string that can be useful for debugging
* `resourceType`: The type of resource that is primarily affected by this request. This is

  the [resource slice](/resources/resource-reducers) that the request will be stored in.
* `ids`: The resource IDs that are affected by this request
* `status`: The "request status" of this request. This represents the state that the

  request is in. It is one of "IDLE", "PENDING", "SUCCEEDED", or "FAILED".

After a successful request to read a user's favorite books, the books resource slice might look something like the following:

```javascript
{
  resourceType: 'books',
  resources: {
    // resources here
  },
  meta: {
    // resource metadata here
  },
  lists: {
    // books lists here
  },
  requests: {
    readFavoriteBooks: {
      requestKey: 'readFavoriteBooks',
      ids: ['1403', '1051', '93'],
      status: 'SUCCEEDED'
    }
  }
}
```

The next few guides will cover these properties of requests in greater detail.


# Keys

A request key is a string used to identify the request within the store. Request keys are conceptually similar to resource IDs.

Request keys can be manually created, or you can use a key that is generated for you by a library. This guide will cover both approaches.

For a request to create a new book, you might use the string `"createBook"`. The resource slice in this situation might look like:

```javascript
{
  resourceType: 'books',
  requests: {
    createBook: {
      requestKey: 'createBook',
      status: 'SUCCEEDED',
      ids: [24]
    }
  },
  // ...there are other things here, too
}
```

This request object represents that this request succeeded, and that the resource with ID of 24 was created.

## Specifying a Request Key

Add the `requestKey` property to a [request action](/requests/request-actions) to specify the key for that request.

```javascript
import { actionTypes } fom 'redux-resource';
import store from './store';

store.dispatch({
  type: actionTypes.READ_RESOURCES_PENDING,
  resourceType: 'books',
  requestKey: 'searchBooks',
});
```

Every request has two actions associated with it: one when the request starts, and one when the request ends. You should use the same request key for both of these actions. For instance, if you use a particular key for the "pending" action, then you will want to use that same key for the "success" action, too.

> Note: if you specify the `request` property on an action, then it will be used as both the key and the [name](https://github.com/jamesplease/redux-resource/tree/5894ec8e4f99f7972443a3fa0b2331e4044bee75/docs/resources/request-names.md). This API is from Redux Resource < 3.0. Although it will continue to work into the future, it is recommended that you explicitly set `requestKey` and `requestName` separately going forward.

## Manual Request Keys

It is okay if you are not using a library that generates a request key for you. You will manually specify your request keys, which isn't too hard to do if you follow a naming convention.

Here are some example request keys you could use:

* `createBook`
* `fetchBook`
* `fetchBooks`
* `updateBook`
* `deleteBook`

We recommend using a verb somewhere in the request key or name. Some good CRUD-related verbs are:

* create
* get
* read
* fetch
* retrieve
* search
* find
* filter
* update
* change
* delete
* remove

If you're associating the request with a [list](https://github.com/jamesplease/redux-resource/tree/5894ec8e4f99f7972443a3fa0b2331e4044bee75/docs/requests/requests/updating-lists.md), then you may want to use the list name in the request key/name as well. For instance, if the list is `favorites`, and the request is for a user searching through their favorites, then you may use `searchFavorites` as the key.

## Generated Request Keys

> Note: Official React bindings for Redux Resource are in the works, and it will generate request keys for you. This section describes how you might go about using generated request keys in your application today.
>
> Keep in mind that it is okay to use manually created keys. Generated keys aren't necessarily better.

If you're using a networking library that provides you with caching and/or request deduplication features, then it may provide you with an identifying string that it generates for each request. It may even call that string a key.

For instance, the libraries [React Request](https://github.com/jamesplease/react-request) and [fetch-dedupe](https://github.com/jamesplease/fetch-dedupe) are both HTTP request libraries that generate keys for you. If you're using those libraries with Redux Resource, then you can use the key that they provide to you as the request key.

This example demonstrates using fetch-dedupe inside of a thunk action creator:

```javascript
import { getRequestKey, fetchDedupe } from 'fetch-dedupe';

export function fetchBooks(bookId) {
  const url = `/books/${bookId}`;
  const fetchOptions = { credentials: 'include' };

  const requestKey = getRequestKey({ url, method: 'GET' });
  const dedupeOptions = { requestKey };

  dispatch({
    type: 'READ_RESOURCES_PENDING',
    resourceType: 'books',
    resources: [bookId]
    requestKey,
  });

  return (dispatch) => {
    fetchDedupe(url, fetchOptions, dedupeOptions)
      .then(res => {
        dispatch({
          type: 'READ_RESOURCES_SUCCEEDED',
          resourceType: 'books',
          resources: [res.data],
          requestKey,
        });

        return res;
      })
      .catch(err => {
        dispatch({
          type: 'READ_RESOURCES_FAILED',
          resourceType: 'books',
          resources: [bookId],
          requestKey,
        });

        return err;
      });
  }
}
```

A problem that needs to be solved when using generated request keys is retrieving the request data from the store within your components. We encourage you to write a component that provides you with a `mapStateToProps` that fetches the request information automatically for you. Official React bindings for Redux Resource are being developed, and that is how it will work. It will use the library [React Request](https://www.github.com/jamesplease/react-request) under-the-hood.

## When to Use Request Keys

We recommend using a request key for every request. In some situations, though, you can use resource metadata in lieu of a request object. When resources are being modified, they have built-in metadata (such as `readStatus`) that will be updated to reflect the action that is modifying them. This alternative approach can be considered a convenience.

If you're manually creating request keys, then a rule of thumb to reduce the boilerplate that you write is:

**Use a request key anytime that you do not have an ID, or a list of IDs, when you dispatch a "pending" action.**

For example, if you attempt to fetch a book with ID of 23, then you *will* have an ID when you dispatch the "read pending" action (the ID is 23). So a request key may not be necessary in this situation, since you can look up the request status on book 23's metadata.

On the other hand, if you were to make a request to your backend for "the list of books that were just released this past week," then you wouldn't have any IDs at the time that you dispatch the "read pending" action. So you *need* to use a request key in this situation to determine the request status.

## An Example

When a request key is used, the status of the associated request is stored in your state, and you can access it with [`getStatus`](/api-reference/get-status):

```javascript
import { getStatus } from 'redux-resource';
import store from './store';

const state = store.getState();
const searchStatus = getStatus(state, 'books.requests.search.status');
// => Returns the following object:
//
// {
//   idle: false,
//   pending: true,
//   failed: false,
//   succeeded: false
// }
//
```

When the request succeeds, you dispatch the following action:

```javascript
import { actionTypes } fom 'redux-resource';
import store from './store';

store.dispatch({
  type: actionTypes.READ_RESOURCES_SUCCEEDED,
  resourceType: 'books',
  request: 'search',
  // `newResources` are the list of books that were returned by the server
  // for this query.
  resources: newResources
});
```

Now when you call `getStatus` using this request key, you get the following object:

```javascript
{
  idle: false,
  pending: false,
  failed: false,
  succeeded: true
}
```

## "Reusing" a Request Key

Request keys differ from IDs in that they don't need to be unique for every request. They can be, and will frequently be, reused between different requests of the same 'type.'

For instance, if a user can create books in your application, then you could just use the key `createBook` for every creation request. This works really well if you can assume that a user is only able to send off one of these create requests at a time, which is a restriction that many applications adhere to.

We don't encourage using the same request key across different 'types' of actions. For instance, if a user can create favorite books, as well as delete favorite books, you should use something like `createFavorite` and `deleteFavorite` for these two actions, rather than, say, using `changeFavorites` for both. This makes your code more expressive, and also allows you to track both requests in the event that they are both in flight at the same time.

### A Note on Dynamic Keys

Developers who manually create request keys tend to make dynamic request keys. A dynamic request key is any key that includes a variable, such as:

```
`fetchBook:${bookId}`
```

Dynamic keys can be useful, but you can frequently get away with static keys.

Here are some use cases for dynamic keys:

* Implementing response caching using request keys. If you plan to implement client-side caching, then you could get a more granular cache by storing some extra information about the request in the store. For more, check out [the recipe on caching](/recipes/caching).
* Supporting multiple of the same 'type' of request at once. If a user can delete a book, and then, while that first request is loading, initiate a second request to delete another book, then you will want two loading indicators on your app.

  A static request key, such as `deleteBook`, won't be enough to capture this information. You might choose to use a dynamic request key in this situation.

If you aren't doing either of those things, then it may be worth considering if you could keep things simple by just using a static key.


# Names

Request names are a feature that can be useful if you are automatically generating [request keys](https://github.com/jamesplease/redux-resource/tree/1c36f09df60425f1f43625c6e32f746b6af33e15/docs/requests/requests/request-keys.md). If you are not automatically generating request keys, then you probably do not need to use request names.

## Motivation

Automatically-generated request keys are useful for advanced networking features such as response caching and request deduplication, but they are often an inconvenience when it comes to debugging code.

For instance, if you have an endpoint that allows a user to run a search, two searches against the endpoint may have the keys "aBui9Xc" and "9d8cdd3". These keys don't communicate the *purpose* of these requests; they are just arbitrary strings.

Providing a request name can help developers who are debugging the application. In that situation, a request name like `"searchBooks"` could be specified. Later, when a developer is looking at the request, they will have some context on what the intention of the request is.

Request names are like function names in JavaScript. Although we could use anonymous functions everywhere, we tend to provide names for our functions so that developers know what they do.

In summary, request names are optional, human-readable descriptions of what the request's intention is.

## Specifying a Request Name

Add the `requestName` property to a [request action](/requests/request-actions) to specify a name for that request.

```javascript
import { actionTypes } fom 'redux-resource';
import store from './store';

store.dispatch({
  type: actionTypes.READ_RESOURCES_PENDING,
  resourceType: 'books',

  // In this situation, we are generating a key. It could be a random string of data,
  // which makes debugging hard.
  requestKey: generateRequestKey(/* request data */),

  // By specifying a human-readable name, we are helping future developers out who are
  // debugging our application.
  requestName: 'searchBooks'
});
```

Every request has two actions: a start action, and an end action. You should specify the name for both of these actions. For more on request actions, refer to the [request actions guide](https://github.com/jamesplease/redux-resource/tree/1c36f09df60425f1f43625c6e32f746b6af33e15/docs/requests/requests/request-actions.md).

> Note: if you specify the `request` property on an action, then it will be used as both the key and the name. This API is from Redux Resource < 3.0. Although it will continue to work into the future, it is recommended that you explicitly set `requestKey` and `requestName` separately going forward.


# Statuses

A request has a "status" associated with it, which represents the state that the request is in. There are four statuses:

* `IDLE`: The request hasn't started yet
* `PENDING`: The request is in flight, and hasn't finished
* `FAILED`: The request finished, and failed
* `SUCCEEDED`: The request finished, and was successful

A request has exactly one status at any given time. Here is an example request object that is in a pending state:

```javascript
{
  requestKey: 'createBook',
  status: 'PENDING'
}
```

The request status values are exported as [`requestStatuses`](/api-reference/request-statuses).

> Note: the request status is different from an HTTP status code. A request that represents an HTTP request could *also* have a status code associated with it, such as 200 or 404.

## Why Use Request Statuses

The status of a request is useful for showing feedback to users of the application. When a request is in the pending state, you can display a loading indicator, and when it is failed, you can show an error message.

## The Status Lifecycle

The request status can be thought of as a cyclical lifecycle. Every request starts as `IDLE`. When the request begins, it moves to `PENDING`.

When it resolves, it becomes `SUCCEEDED` or `FAILED` depending on the outcome.

And lastly, there may be a time when you no longer need to display to the user that the request has succeeded or failed. At this time, you can make the request `IDLE` again.

If the application makes the same request again, the process will repeat itself.

Not every request needs to go through the entire lifecycle. Sometimes, requests will sit indefinitely in the `SUCCEEDED` state after they resolve. Other times, you may need to "reset" the state back to `IDLE`.

> Note: when a request is aborted, we recommend that you move it back to the `IDLE` state. Webapps typically abort requests because the user no longer needs to know if the request succeeds or fails.

## Providing More Detailed Information

The request status provides a coarse representation of the status of the request, but you will frequently need more granular information. Why did the request fail? Was the resource not found, or did the backend have an error? Is the user logged out, or did they lose their network connection?

You can store additional data on a request to capture information like this.

For instance, if your requests represent RESTful HTTP calls, then you could add the HTTP status code to the request. Or, if your requests represent gRPC calls, then you could place the gRPC error code onto the request, too.

The request definition is intentionally flexible. It allows you store any additional information that you need. This enables Redux Resource's requests to work with any networking layer: RESTful HTTP endpoints, GraphQL, gRPC, web sockets, or whatever else you may be using to transfer data.


# Request Actions

Any time that you need to interact with resources over a network, you should use request actions.

> Note: to make synchronous changes to a resource slice, you can use [the synchronous actions](/resources/modifying-resources) instead.

## Requests Require Two Actions

Requests are asynchronous, so they take time to complete. First, a network request is sent off, and then sometime later it resolves.

In Redux Resource, this information is captured using two actions. Any time that you make a request, you will need to dispatch both of these actions. The first is dispatched just before the request begins, and the second is dispatched once the request completes.

For instance, the sequence of action types for a successful read request would be the following:

`READ_RESOURCES_PENDING` ⇨ `READ_RESOURCES_SUCCEEDED`

The `PENDING` action is always the "start" action. It is dispatched just before the request begins. Then, once the request succeeds, or fails, or is cancelled, you dispatch the "end" action (`SUCCEEDED` in this case).

> Note: the [redux-thunk](https://github.com/gaearon/redux-thunk) middleware is a great solution for supporting asynchronous action creators like the ones necessary for dispatching request actions.

## Action Properties

These are the following properties that you may include on a request action:

* `type`: The action type. The full list of request action types can be viewed

  [here.](/api-reference/action-types)
* `resourceType`: The type of the resource that is primarily being affected by this request
* `resources`: An array of affected resources
* `requestKey`: The request key
* `requestName`: The request name
* `list`: The list to add the resources to
* `requestProperties`: Additional data to store on the request
* `mergeResources`: A Boolean representing whether or not new resources are merged with

  existing resources. Defaults to `true`.
* `mergeMeta`: A Boolean representing whether or not new resource metadata is merged with

  existing resource metadata. Defaults to `true`.
* `mergeListIds`: A Boolean representing whether or not the new resources should replace

  an existing list or not. Defaults to `true`.

This section of this guide will cover these properties in more detail.

All request actions have a single required property, `resourceType`, which is the name of the resource that is being affected. The simplest action, then, looks something like this:

```javascript
import { actionTypes } from 'redux-resource';
import store from './store';

store.dispatch({
  type: actionTypes.READ_RESOURCES_PENDING,
  resourceType: 'books'
});
```

This action isn't very useful, however. Without more information about this request, Redux Resource doesn't know where to put this information in your state tree, so this action doesn't change the store.

To reflect a request status in the state tree, you need to supply at least one of these two values in your action: a `resources` array, or a `requestKey`.

## `resources`

A `resources` array represents the resources being affected by the action. It can be an array of IDs, such as `[1, 2, 3]`, or an array of resource objects, such as

```javascript
[
  {
    id: 1,
    name: 'Brian',
    phone: '444.444.4444'
  },
  {
    id: 2,
    name: 'Sarah',
    phone: '222.222.2222'
  }
]
```

You can even mix the two. When it comes to a `resources` array, the important part is that the objects have some `id`. This associates the action with some resources.

You may be wondering when you might use the object form versus the shorthand form. There are two guidelines to remember, one for the start action, and one for the end action.

**For the start action, provide IDs, if you have them.**

**For the end action, provide the full resource definitions, if you have them. If you don't, but you do have IDs, then provide those.**

Let's look at an example.

If you're reading a single resource, such as a book, then you might access that book from your backend service with its ID. In this situation, you will have an ID at the time that you dispatch the start action, so we include that ID in the action's `resources` array:

```javascript
import { actionTypes } from 'redux-resource';
import store from './store';

store.dispatch({
  type: actionTypes.READ_RESOURCES_PENDING,
  resourceType: 'books',
  resources: [23]
});
```

When the request succeeds, you now have more detailed information about this book to add to your store. So you would include the full book definition in the success action's `resources`:

```javascript
import { actionTypes } from 'redux-resource';
import store from './store';

store.dispatch({
  type: actionTypes.READ_RESOURCES_SUCCEEDED,
  resourceType: 'books',
  resources: [{
    id: 23,
    releaseYear: 2015,
    author: 'Jane M. Goodfellow',
    title: 'A History of Canada'
  }]
});
```

Whenever a `resources` array is supplied, Redux Resource will update the `meta` for each resource in that array.

The "success" action types also have special behavior with the `resources` array. For creates, reads, and updates, your state's resources object will be updated to reflect any new data. For successful deletes, the state for that resource will be changed to be `null`, and the resource will be removed from the `ids` array of all lists.

It isn't always possible to provide an array of `resources` in your action. For instance, if the user is searching for books by entering a title, you couldn't know which books will be returned until after the request has completed.

To keep track of the resources for requests like these, you need to use request objects.

## `requestKey`

Supplying a `requestKey` will create a [request object](https://github.com/jamesplease/redux-resource/tree/1c36f09df60425f1f43625c6e32f746b6af33e15/docs/requests/requests/request-objects.md) for this operation within the `requests` section of the resource slice.

For instance, if your interface allows users to search for a books resource, you might dispatch the following action:

```javascript
import { actionTypes } from 'redux-resource';
import store from './store';

store.dispatch({
  type: actionTypes.READ_RESOURCES_PENDING,
  resourceType: 'books',
  requestKey: 'booksSearch',
});
```

## `requestName`

A human-readable string to help with debugging. For more, refer to the [Request Keys and Names](https://github.com/jamesplease/redux-resource/tree/1c36f09df60425f1f43625c6e32f746b6af33e15/docs/requests/requests/keys-and-names.md) guide.

```javascript
import { actionTypes } from 'redux-resource';
import store from './store';

store.dispatch({
  type: actionTypes.READ_RESOURCES_PENDING,
  resourceType: 'books',
  // In this example, we have some system to generate our request keys for us.
  // This could be used by a system to implement request deduplication or
  // response caching. An example library that generates request keys for you
  // is fetch-dedupe:
  // https://github.com/jamesplease/fetch-dedupe
  requestKey: generateRequestKey(/* request options */),

  // Because the request key is a randomly generated string, it can be convenient
  // to know what the purpose of this request is.
  requestName: 'searchBooks'
});
```

## `list`

For create and read operations, you can supply a `list` on a request action. This will add the resources returned from the operation to the specified list on your slice.

> Note: you'll nearly always want to provide a request key when using lists. This is so that you can track the status of the request on the request object.

```javascript
import { actionTypes } from 'redux-resource';
import store from './store';

store.dispatch({
  type: actionTypes.READ_RESOURCES_PENDING,
  resourceType: 'books',
  list: 'mostPopular',
  requestKey: 'getMostPopular',
});
```

To learn more about lists, refer to [the lists guide](/resources/lists).

## Other Request Action properties

The following Request Action properties are all optional.

* `mergeResources` *(Boolean)*: When an action results in resources being updated in the store, this determines if the new data is merged with the old, or if it replaces the old data. Defaults to `true`. This only has an effect on successful read, write, and update Actions.
* `mergeMeta` *(Boolean)*: This is like `mergeResources`, but for metadata. Defaults to `true`. This property works with actions with any of the request action types.
* `mergeListIds` *(Boolean)*: When a list is supplied, this lets you control whether or not the new list of IDs replaces or gets merged into the existing list of IDs for that list. When `true`, it will protect against duplicate IDs being added. Defaults to `true`. This only applies for successful read and write Actions that have a `list` specified.
* `requestProperties` *(Object)*: An object that will be merged onto the request object. Use this to add additional data onto the request object, such as HTTP status codes, gRPC error codes, or any other information related to the request.

## Dreprecated Request Action Properties

The following request action properties are deprecated, and will be removed in the next major release of Redux Resource (4.0.0):

* `request` *(String)*: A convenient way to set both the `requestKey` and the `requestName` at the same time.
* `resourceName` *(String)*: An alias of `resourceType`. Use `resourceType` instead.

## Action Creators

The core Redux Resource library does not include action creators, but there is [a library, Redux Resource XHR](/extras/redux-resource-xhr), that includes action creators.

You're also free to build your own action creators. For examples, refer to these four guides:

* [Reading Resources](/requests/request-actions/reading-resources)
* [Updating Resources](/requests/request-actions/updating-resources)
* [Creating Resources](/requests/request-actions/creating-resources)
* [Deleting Resources](/requests/request-actions/deleting-resources)

## Using the Action Types

One of this library's exports are these request action types. You can use them in your application by importing them like so:

```javascript
import { actionTypes } from 'redux-resource';
```

For a complete list of all of the action types, refer to the [Action Types API Reference](/api-reference/action-types).


# Updating Lists

When a request succeeds, you will frequently want to add the resources returned by the response to a [list](/resources/lists). There is a convenient way to do this using the [request actions](https://github.com/jamesplease/redux-resource/tree/e0d24c6c69879d54e94c1ab9976b4b6a9d5adb7f/docs/requests/requests/request-actions.md).

> Note: if you're not familiar with resource lists, then you may want to read [the documentation for them](/resources/lists) before continuing.

## Specifying a List

To specify the list to add the resources to, add the `list` property to a 'successful' [request action](/requests/request-actions).

```javascript
import { actionTypes } fom 'redux-resource';
import store from './store';

store.dispatch({
  type: actionTypes.READ_RESOURCES_SUCCEEDED,
  resourceType: 'books',
  list: 'mostPopular',
  requestKey: 'getMostPopular'
  // `newResources` is the list of books that were returned by the server
  // for this request.
  resources: newResources
});
```

You only need to specify a list for create or read *success* actions. Nothing happens if you specify a list for an update or delete action.

> Note: deleted resources will automatically be removed from any list that they are included in.

## Why Specify a List

There are two main reasons to specify a list when making a request. The [`getResources`](/api-reference/get-resources) function lets you quickly access resources given a list name.

For instance, if you specify the list `"favoriteBooks"` when a request succeeds for fetching a user's favorite books, then you can access the resources returned by that request using the following snippet:

```javascript
import { getResources } from 'redux-resource';
import store from './my-store';

const state = store.getState();
const favoriteBooks = getResources(state.books, 'favoriteBooks');
```

Convenience aside, lists enable you to do sligtly complicated, but common task that is more difficult to do otherwise. The situation it helps in is where the application fetches a collection of resources that the user can then modify.

An example may help demonstrate this. Consider a page that displays a user's favorite books. When the user navigates to the page, a request to fetch the favorite books is made.

After the request completes, the user is able to add or delete favorite books. After they add or delete a book, you want the favorite books that are displayed to them to reflect their changes.

There are two ways to do this:

1. after the create or delete request succeeds, you make a second request to fetch

   the list of favorite books a second time, so that the list is up-to-date
2. after the create or delete request succeeds, you update the local list of favorite books

   without making a second request

Both of these approaches are great. You can do whichever you think is best.

If you decide to go with the second method, then using a list makes this straightforward to do. It works like this: when the request to fetch the favorite books succeeds, you can add the resources to the `favoriteBooks` list. Then, when the user creates or deletes a new favorite book, you modify the list.

## Replacing List IDs

By default, subsequent requests with the same list will *merge* the old list IDs with the new IDs. You can replace the old list with the new by passing `mergeListIds: false` in your action. For instance:

```javascript
import { actionTypes } fom 'redux-resource';
import store from './store';

store.dispatch({
  type: actionTypes.READ_RESOURCES_SUCCEEDED,
  resourceType: 'books',
  list: 'mostPopular',
  mergeListIds: false,
  // `newResources` is the list of books that were returned by the server
  // for this request.
  resources: newResources
});
```

## More Reading

For more on lists, refer to [the lists guide](/resources/lists) and [the Lists FAQ](/faq/lists).


# Reading Resources

Redux Resource provides four [action types](/requests/request-actions) for reading resources asynchronously. They are:

```javascript
"READ_RESOURCES_PENDING"
"READ_RESOURCES_FAILED"
"READ_RESOURCES_SUCCEEDED"
"READ_RESOURCES_IDLE"
```

Each request will always begin with an action with type `READ_RESOURCES_PENDING`. Then, one of the other three action types will be used to represent the resolution of that request. Use the other action types in the following way:

* `READ_RESOURCES_FAILED`: Use this if the request fails for any reason. This

  could be network errors, or any

  [HTTP Status Code](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes)

  greater than or equal to 400.
* `READ_RESOURCES_IDLE`: Use this when the request is aborted.
* `READ_RESOURCES_SUCCEEDED`: Use this when the request was successful.

## Request Objects

Specifying a [request key](https://github.com/jamesplease/redux-resource/tree/1c36f09df60425f1f43625c6e32f746b6af33e15/docs/requests/requests/request-keys.md) on the actions will create a request object in the store for this request. This object can be used to look up the [status](https://github.com/jamesplease/redux-resource/tree/1c36f09df60425f1f43625c6e32f746b6af33e15/docs/requests/requests/request-statuses.md) of the request.

Although it is recommended that you specify a request key when possible, there are some situations when you may not need to when fetching resources.

When fetching a single resource, you typically provide the ID to be fetched. Therefore, [request objects](https://github.com/jamesplease/redux-resource/tree/1c36f09df60425f1f43625c6e32f746b6af33e15/docs/requests/requests/request-objects.md) aren't always necessary, as you can track the request on the resource's metadata directly.

For read requests that return multiple resources, it is typically preferable to specify a request key.

## Successful Reads

When an action of type `READ_RESOURCES_SUCCEEDED` is dispatched, three things will happen:

1. the resources included in the action's `resources` will be added to the `resources` section of the resource slice. Existing resources with the same ID will be merged with the new ones. To replace existing resources, rather than merge them, specify `mergeResources: false` on the action.
2. The metadata for each of the `resources` specified on the action will be updated with `readStatus: 'SUCCEEDED'`. To replace all of the existing meta, rather than merging it, specify `mergeMeta: false` on the action.
3. When a `list` is passed, the IDs from the `resources` array on the action will be added to the list. You may specify `mergeListIds: false` to *replace* the existing list instead.

## Redux Resource XHR

[Redux Resource XHR](/extras/redux-resource-xhr) provides an action creator that simplifies making CRUD requests. If you'd like to build your own, then that's fine, too. The example below may help.

## Example Action Creator: Reading One Resource

This example shows an action creator to read a single book. It uses the [redux-thunk](https://github.com/gaearon/redux-thunk) middleware and the library [xhr](https://github.com/naugtur/xhr) for making requests.

```javascript
import { actionTypes } from 'redux-resource';
import xhr from 'xhr';

export default function readBook(bookId) {
  return function(dispatch) {
    dispatch({
      type: actionTypes.READ_RESOURCES_PENDING,
      resourceType: 'books',
      resources: [bookId],
    });

    const req = xhr.get(
      `/books/${bookId}`,
      {json: true},
      (err, res, body) => {
        if (req.aborted) {
          dispatch({
            type: actionTypes.READ_RESOURCES_IDLE,
            resourceType: 'books',
            resources: [bookId],
          });
        } else if (err || res.statusCode >= 400) {
          dispatch({
            type: actionTypes.READ_RESOURCES_FAILED,
            resourceType: 'books',
            resources: [bookId],
            requestProperties: {
              statusCode: res.statusCode 
            }
          });
        } else {
          dispatch({
            type: actionTypes.READ_RESOURCES_SUCCEEDED,
            resourceType: 'books',
            resources: [body],
            requestProperties: {
              statusCode: res.statusCode 
            }
          });
        }
      }
    );

    return req;
  }
}
```

## Example Action Creator: Reading Many Resource

This example shows an action creator to read multiple books. It uses the [redux-thunk](https://github.com/gaearon/redux-thunk) middleware and the library [xhr](https://github.com/naugtur/xhr) for making requests. To create a query string, it uses the [querystring module](https://github.com/Gozala/querystring).

```javascript
import { actionTypes } from 'redux-resource';
import xhr from 'xhr';
import qs from 'querystring';

export default function readBooks(query) {
  return function(dispatch) {
    dispatch({
      type: actionTypes.READ_RESOURCES_PENDING,
      resourceType: 'books',
      requestKey: 'search',
      requestProperties: {
        statusCode: null
      }
    });

    const queryString = qs.stringify(query);

    const req = xhr.get(
      `/books?${queryString}`,
      {json: true},
      (err, res, body) => {
        if (req.aborted) {
          dispatch({
            type: actionTypes.READ_RESOURCES_IDLE,
            resourceType: 'books',
            requestKey: 'search',
            requestProperties: {
              statusCode: null
            }
          });
        } else if (err || res.statusCode >= 400) {
          dispatch({
            type: actionTypes.READ_RESOURCES_FAILED,
            resourceType: 'books',
            requestKey: 'search',
            requestProperties: {
              statusCode: res.statusCode 
            }
          });
        } else {
          dispatch({
            type: actionTypes.READ_RESOURCES_SUCCEEDED,
            resourceType: 'books',
            requestKey: 'search',
            resources: body,
            requestProperties: {
              statusCode: res.statusCode 
            }
          });
        }
      }
    );

    return req;
  }
}
```


# Updating Resources

Redux Resource provides four [action types](/requests/request-actions) for updating resources asynchronously. They are:

```javascript
"UPDATE_RESOURCES_PENDING"
"UPDATE_RESOURCES_FAILED"
"UPDATE_RESOURCES_SUCCEEDED"
"UPDATE_RESOURCES_IDLE"
```

Each request will always begin with an action with type `UPDATE_RESOURCES_PENDING`. Then, one of the other three action types will be used to represent the resolution of that request. Use the other action types in the following way:

* `UPDATE_RESOURCES_FAILED`: Use this if the request fails for any reason. This

  could be network errors, or any

  [HTTP Status Code](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes)

  greater than or equal to 400.
* `UPDATE_RESOURCES_IDLE`: Use this when the request is aborted.
* `UPDATE_RESOURCES_SUCCEEDED`: Use this when the request was successful.

## Request Objects

Specifying a [request key](https://github.com/jamesplease/redux-resource/tree/a26887faf6296cd4c1b78b6fe9589a385234225f/docs/requests/requests/request-keys.md) on the actions will create a request object in the store for this request. This object can be used to look up the [status](https://github.com/jamesplease/redux-resource/tree/a26887faf6296cd4c1b78b6fe9589a385234225f/docs/requests/requests/request-statuses.md) of the request.

Although it is recommended that you specify a request key whenever possible, there are some situations when you may not need to when updating resources.

For updates that target a single resource, you typically know the ID being updated upfront. Accordingly, you could use the resource metadata to track the status.

For update requests that return multiple resources, it is typically preferable to specify a request key.

## Successful Updates

When an action of type `UPDATE_RESOURCES_SUCCEEDED` is dispatched, three things will happen:

1. the resources included in the action's `resources` will be added to the `resources` section of the resource slice. Existing resources with the same ID will be merged with the new ones. To replace existing resources, rather than merge them, specify `mergeResources: false` on the action.
2. The metadata for each of the `resources` specified on the action will be updated with `updateStatus: 'SUCCEEDED'`. To replace all of the existing meta, rather than merging it, specify `mergeMeta: false` on the action.
3. When a `list` is passed, the IDs from the `resources` array on the action will be added to the list. You may specify `mergeListIds: false` to *replace* the existing list instead.

## Redux Resource XHR

[Redux Resource XHR](/extras/redux-resource-xhr) provides an action creator that simplifies making CRUD requests. If you'd like to build your own, then that's fine, too. The example below may help.

## Example Action Creator

This example shows an action creator to update a single book. It uses the [redux-thunk](https://github.com/gaearon/redux-thunk) middleware and the library [xhr](https://github.com/naugtur/xhr) for making requests.

```javascript
import { actionTypes } from 'redux-resource';
import xhr from 'xhr';

// `bookDetails` could have the following shape:
//
// {
//   id: 23,
//   published: true
// }
//
export default function updateBook(bookDetails) {
  return function(dispatch) {
    dispatch({
      type: actionTypes.UPDATE_RESOURCES_PENDING,
      resourceType: 'books',
      // You can pass either the whole `bookDetails`, or just the ID. Both work.
      // Just be sure to pass the whole object on success, so that the updated
      // attributes are persisted to your state tree!
      resources: [bookDetails.id],
    });

    const req = xhr.patch(
      `/books/${bookDetails.id}`,
      {
        json: bookDetails
      },
      (err, res, body) => {
        if (req.aborted) {
          dispatch({
            type: actionTypes.UPDATE_RESOURCES_IDLE,
            resourceType: 'books',
            resources: [bookDetails.id],
          });
        } else if (err || res.statusCode >= 400) {
          dispatch({
            type: actionTypes.UPDATE_RESOURCES_FAILED,
            resourceType: 'books',
            resources: [bookDetails.id],
            requestProperties: {
              statusCode: res.statusCode 
            }
          });
        } else {
          dispatch({
            type: actionTypes.UPDATE_RESOURCES_SUCCEEDED,
            resourceType: 'books',
            resources: [body],
            requestProperties: {
              statusCode: res.statusCode 
            }
          });
        }
      }
    );

    return req;
  }
}
```


# Creating Resources

Redux Resource provides four [action types](/requests/request-actions) for creating resources asynchronously. They are:

```javascript
"CREATE_RESOURCES_PENDING"
"CREATE_RESOURCES_FAILED"
"CREATE_RESOURCES_SUCCEEDED"
"CREATE_RESOURCES_IDLE"
```

Each request will always begin with an action with type `CREATE_RESOURCES_PENDING`. Then, one of the other three action types will be used to represent the resolution of that request. Use the other action types in the following way:

* `CREATE_RESOURCES_FAILED`: Use this if the request fails for any reason. This

  could be network errors, or any

  [HTTP Status Code](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes)

  greater than or equal to 400.
* `CREATE_RESOURCES_IDLE`: Use this when the request is aborted.
* `CREATE_RESOURCES_SUCCEEDED`: Use this when the request was successful.

## Request Objects

Specifying a [request key](https://github.com/jamesplease/redux-resource/tree/ff34214a0fa09cddc61b2b011fab04bc4105f8a3/docs/requests/requests/request-keys.md) on the actions will create a request object in the store for this request. This object can be used to look up the [status](https://github.com/jamesplease/redux-resource/tree/ff34214a0fa09cddc61b2b011fab04bc4105f8a3/docs/requests/requests/request-statuses.md) of the request.

For many create requests, you don't have the ID of the resource being created until after the operation succeeds. Therefore, to track the status of the request, you will need to specify the request key so that the status can be stored on the request object.

Many interfaces only allow one creation request at a time (although that request may be for a bulk creation). In these situations, you can just use a single request key, such as `"create"`, for all of your creation requests.

## Successful Creates

When an action of type `CREATE_RESOURCES_SUCCEEDED` is dispatched, three things will happen:

1. the resources included in the action's `resources` will be added to the `resources` section of the resource slice. Existing resources with the same ID will be merged with the new ones. To replace existing resources, rather than merge them, specify `mergeResources: false` on the action.
2. The metadata for each of the `resources` specified on the action will be updated with `createStatus: 'SUCCEEDED'`. To replace all of the existing meta, rather than merging it, specify `mergeMeta: false` on the action.
3. When a `list` is passed, the IDs from the `resources` array on the action will be added to the list. You may specify `mergeListIds: false` to *replace* the existing list instead.

## Redux Resource XHR

[Redux Resource XHR](/extras/redux-resource-xhr) provides an action creator that simplifies making CRUD requests. If you'd like to build your own, then that's fine, too. The example below may help.

## Example Action Creator

This example shows an action creator to create a single book. It uses the [redux-thunk](https://github.com/gaearon/redux-thunk) middleware and the library [xhr](https://github.com/naugtur/xhr) for making requests.

```javascript
import { actionTypes } from 'redux-resource';
import xhr from 'xhr';

export default function createBook(bookDetails) {
  return function(dispatch) {
    dispatch({
      type: actionTypes.CREATE_RESOURCES_PENDING,
      resourceType: 'books',
      requestKey: 'create',
    });

    const req = xhr.post(
      '/books',
      {
        json: bookDetails
      },
      (err, res, body) => {
        if (req.aborted) {
          dispatch({
            type: actionTypes.CREATE_RESOURCES_IDLE,
            resourceType: 'books',
            requestKey: 'create',
          });
        } else if (err || res.statusCode >= 400) {
          dispatch({
            type: actionTypes.CREATE_RESOURCES_FAILED,
            resourceType: 'books',
            requestKey: 'create',
            requestProperties: {
              statusCode: res.statusCode 
            }
          });
        } else {
          dispatch({
            type: actionTypes.CREATE_RESOURCES_SUCCEEDED,
            resourceType: 'books',
            requestKey: 'create',
            resources: [body],
            requestProperties: {
              statusCode: res.statusCode 
            }
          });
        }
      }
    );

    return req;
  }
}
```


# Deleting Resources

Redux Resource provides four [action types](/requests/request-actions) for deleting resources asynchronously. They are:

```javascript
"DELETE_RESOURCES_PENDING"
"DELETE_RESOURCES_FAILED"
"DELETE_RESOURCES_SUCCEEDED"
"DELETE_RESOURCES_IDLE"
```

Each request will always begin with an action with type `DELETE_RESOURCES_PENDING`. Then, one of the other three action types will be used to represent the resolution of that request. Use the other action types in the following way:

* `DELETE_RESOURCES_FAILED`: Use this if the request fails for any reason. This

  could be network errors, or any

  [HTTP Status Code](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes)

  greater than or equal to 400.
* `DELETE_RESOURCES_IDLE`: Use this when the request is aborted.
* `DELETE_RESOURCES_SUCCEEDED`: Use this when the request was successful.

## Request Objects

Specifying a [request key](https://github.com/jamesplease/redux-resource/tree/e0d24c6c69879d54e94c1ab9976b4b6a9d5adb7f/docs/requests/requests/request-keys.md) on the actions will create a request object in the store for this request. This object can be used to look up the [status](https://github.com/jamesplease/redux-resource/tree/e0d24c6c69879d54e94c1ab9976b4b6a9d5adb7f/docs/requests/requests/request-statuses.md) of the request.

Although it is recommended that you specify a request key whenever possible, there are some situations when you may not need to when deleting resources.

Because you usually know the ID of the resources that you're deleting, you may not need to specify a request key for delete operations. The metadata for the delete request can just be stored on the resource metadata directly.

For delete requests that affect multiple resources, it is typically preferable to specify a request key.

## Successful Deletes

When an action of type `DELETE_RESOURCES_SUCCEEDED` is dispatched, three things will happen:

1. The `resources` included in the action will be replaced with `null` in the `resources` section of your resource slice.
2. The `resources` included in the action will be removed from all lists in the resource slice.
3. The value of `deleteStatus` will be set to `"SUCCEEDED"`. All other meta values will be set to the default meta for that resource slice.

## Redux Resource XHR

[Redux Resource XHR](/extras/redux-resource-xhr) provides an action creator that simplifies making CRUD requests. If you'd like to build your own, then that's fine, too. The example below may help.

## Example Action Creator

This example shows an action creator to delete a single book. It uses the [redux-thunk](https://github.com/gaearon/redux-thunk) middleware and the library [xhr](https://github.com/naugtur/xhr) for making requests.

```javascript
import { actionTypes } from 'redux-resource';
import xhr from 'xhr';

export default function deleteBook(bookId) {
  return function(dispatch) {
    dispatch({
      type: actionTypes.DELETE_RESOURCES_PENDING,
      resourceType: 'books',
      resources: [bookId],
    });

    const req = xhr.del(
      `/books/${bookId}`,
      (err, res, body) => {
        if (req.aborted) {
          dispatch({
            type: actionTypes.DELETE_RESOURCES_IDLE,
            resourceType: 'books',
            resources: [bookId],
          });
        } else if (err || res.statusCode >= 400) {
          dispatch({
            type: actionTypes.DELETE_RESOURCES_FAILED,
            resourceType: 'books',
            resources: [bookId],
            requestProperties: {
              statusCode: res.statusCode 
            }
          });
        } else {
          dispatch({
            type: actionTypes.DELETE_RESOURCES_SUCCEEDED,
            resourceType: 'books',
            resources: [bookId],
            requestProperties: {
              statusCode: res.statusCode 
            }
          });
        }
      }
    );

    return req;
  }
}
```


# Other Guides

* [Usage With React](/other-guides/usage-with-react)
* [Tracking Request Statuses](/other-guides/tracking-request-statuses)
* [Using Request Statuses](/other-guides/using-request-statuses)
* [Custom Action Types](/other-guides/custom-action-types)
* [Migration Guides](/other-guides/migration-guides)


# Usage With React

It is not a requirement you should use React to use Redux Resource, but the two work well together. We recommend using the [react-redux](https://github.com/reactjs/react-redux) library to [link Redux with React](http://redux.js.org/docs/basics/UsageWithReact.html).

The following are some patterns that we find ourselves using frequently with Redux Resource.

## Using `mapStateToProps`

We recommend placing your calls to [`getResources`](/api-reference/get-resources) and [`getStatus`](/api-reference/get-status) within `mapStateToProps`. That way, you can access this information from any of the component's lifecycle methods, without needing to compute them within each method.

For example:

```javascript
import { getResources, getStatus } from 'redux-resource';

function mapStateToProps(state) {
  const searchedBooks = getResources(state.books, 'searchResults');
  const searchStatus = getStatus(state, 'books.requests.getSearchResults.status');

  return {
    searchedBooks,
    searchStatus
  };
}
```

## Type Checking with Prop Types

Redux Resource Prop Types exports a number of helpful prop types for common props that you'll pass into your React Components. Read the [Redux Resource Prop Types documentation](/extras/redux-resource-prop-types) for more.

## Using Request Statuses

This is such an important topic that there is a [dedicated guide for it](/other-guides/using-request-statuses).

## Determining When a Request Succeeds

Sometimes, you want to know the exact moment that a request succeeds. You can do this within your components by comparing the previous state with the next state to determine when a request changes from one status to another.

We recommend performing this check within `componentDidUpdate`. This might look like:

```javascript
import { getResources, getStatus } from 'redux-resource';

class BooksList extends Component {
  render() {
    // Render contents here
  }

  // Let's log to the console whenever a search result succeeds
  componentDidUpdate(prevProps) {
    if (this.props.searchStatus.succeeded && prevProps.searchStatus.pending) {
      console.log('The search request just succeeded.');
    }
  }
}


function mapStateToProps(state) {
  const searchStatus = getStatus(state, 'books.requests.getSearchResults.status');

  return {
    searchStatus
  };
}
```

This same approach can also be used to detect the moment that a request fails.


# Tracking Request Statuses

Displaying feedback about CRUD operations requires knowing the [status](/requests/request-statuses) of its request: is it pending, failing, succeeded? This is what we mean by "tracking" a request. The status of a request can be used to display feedback to the user of your application, such as showing loading indicators or error messages.

There are two ways to track CRUD operation requests in Redux Resource: using a [request object](/requests/request-objects), or tracking the status on resource metadata.

Typically, you should use request objects, but in some situations you may prefer to use resource metadata instead.

## Request objects

You can use request objects to track any request that your application makes. Request objects are by far the more powerful of the two options for tracking requests, so we recommend using them whenever possible.

To learn about the shape of request objects, refer to [the request objects guide](/requests/request-objects).

To dispatch actions that create request objects, you need to supply a `requestKey` to with your request actions. For instance,

```javascript
{
  type: actionTypes.READ_RESOURCES_PENDING,
  resourceType: 'books',
  requestKey: 'searchBooks'
}
```

This will update your resource slice to look like the following:

```javascript
{
  resourceType: 'books',
  requests: {
    searchBooks: {
      requestKey: 'searchBooks',
      status: 'PENDING'
    }
  }
}
```

For more on request actions, refer to the [request actions guide](/requests/request-actions).

## Resource Metadata

In a limited number of situations, you may not need to specify a `requestKey` with your request actions.

This is true whenever your CRUD operations directly target a resource, or a set of resources, by their ID. For instance, if the user is fetching a book with ID 23, then this action is directly targeting the book with ID of 23. Likewise, deleting books with IDs 100, 101, and 102 is a request that is targeting these three resources directly.

Any time that you have a set of IDs when the request is sent off, then you can track the status of the operation on the resource metadata directly. You can do this by passing a `resources` array with the start action.

Let's look at an example. The action that represents beginning a read request of a book with ID 24 looks like the following:

```javascript
{
  type: actionTypes.READ_RESOURCES_PENDING,
  resourceType: 'books',
  resources: [24]
}
```

When this is dispatched, your slice's metadata will be updated like this:

```javascript
{
  meta: {
    24: {
      createStatus: 'IDLE',
      readStatus: 'PENDING',
      updateStatus: 'IDLE',
      deleteStatus: 'IDLE'
    }
  }
}
```

In your view layer, you can then use [`getStatus`](/api-reference/get-status) to access this state in a convenient way.

The rule of thumb is:

**You can track CRUD operation requests on resource metadata anytime you have an ID when you fire the "start" action type.**

Although using request objects is optional, we encourage their use because they provide consistency across your code base. Request objects allow you to track the status of *every* request, whereas resource metadata only works in a subset of situations.

## Using Statuses

You now know how to *store* the request statuses in your store. There is a separate guide on [Using Request Statuses](/other-guides/using-request-statuses) in your view layer.


# Using Request Statuses

When request action types are dispatched, Redux Resource will store information about those requests in the store. This guide will cover how you can use those statuses in your view layer.

> Note: these examples are React components using react-redux. Keep in mind that nothing in Redux Resource requires React: if you're using Redux with any other view layer, then this library will work just as well.

## `getStatus`

One of the exports of this library is [`getStatus`](/api-reference/get-status). This function facilitates using Redux Resource request statuses to build your interfaces. It will likely be one of the Redux Resource functions that you rely on the most.

Let's look at an example. Let's say we have a page that displays details about a book. We might write the following component:

```javascript
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { getStatus } from 'redux-resource';

export class BookDetails extends Component {
  render() {
    const { book, readStatus } = this.props;

    return (
      <div>
        {readStatus.pending && 'Loading...'}
        {readStatus.failed && 'There was an error.'}
        {readStatus.succeeded && (
          <div>
            <span>
              {book.title} ({book.id})
            </span>
            <span>
              {book.releaseYear}, {book.author}
            </span>
          </div>
        )}
      </div>
    );
  }
}

function mapStateToProps(state, props) {
  // A user can pass a `bookId` into this Component to view the book's data
  const bookId = props.bookId;
  const readStatus = getStatus(state, `books.meta[${bookId}].readStatus`, true);
  const book = state.books.resources[book.id];

  return {
    book,
    readStatus
  };
}

export default connect(mapStateToProps)(BookDetails);
```

You can see how the object returned from `getStatus` makes a render function very expressive. It's also convenient that there aren't any checks for existence here, even though our data is nested in our store: the API of Redux Resource provides you with very predictable data.

## Aggregating Statuses

Often times, the data displayed on a single page comes from multiple sources. Whenever possible, we recommend using multiple `getStatus` calls in these situations, so that you can display information to the user as it becomes available. This way, if one endpoint is slow, or if the request fails entirely, the rest of the interface isn't affected by it.

With that said, we know this isn't always possible. Sometimes, you simply do need to wait for multiple requests to resolve before there is anything useful to show on the page.

You can use `getStatus` to aggregate these calls together into status. The API for this is as follows:

```javascript
import { getStatus } from 'redux-resource';
import store from './get-store';

const state = store.getState();

const aggregatedStatus = getStatus(state, [
  'books.meta.23.readStatus',
  'books.requests.getBookComments.status'
], true);
```

The rules of aggregation work as follows:

* If **any** status is `failed: true`, then the group is `failed: true`.
* If no status is `failed: true`, but at least one is `pending: true`, then the

  group is `pending: true`.
* If **all** statuses are `succeeded: true`, then the group is

  `succeeded: true`.

At most, only one of these values will ever be `true`.

If `treatIdleAsPending` (the third argument, see below) is `false`, then all three values will be `false` if all of the request statuses in the state tree are `"IDLE"`.

## `treatIdleAsPending`

The third argument to `getStatus` is a Boolean called `treatIdleAsPending`. It determines whether a request status of `"IDLE"` will count as `pending` or not.

Consider an interface that loads a particular book when the page loads. Right at page load, there will always be a short moment when the request hasn't begun, yet your store has been set up. At this moment, the request status for this read will have a value of `"IDLE"`.

If you don't pass `true`, then there will be a "flash of no content" unless you explicitly check for the `"IDLE"` status yourself. To avoid this, pass `treatIdleAsPending` as true, and `getStatus` will instead consider that to be a pending state.

The default value of `treatIdleAsPending` is `false`.

### The Rule of Thumb

There is a rule of thumb for using `treatIdleAsPending`:

* For requests that happen when the page loads, pass `treatIdleAsPending` as `true`
* For requests that happen as a response to a user's action (such as clicking a

  button), pass `treatIdleAsPending` as `false`


# Custom Action Types

You can add support for additional action types to a [`resourceReducer`](/api-reference/resource-reducer) using plugins.

The name 'plugins' may seem intimidating, but don't be worried. Plugins are reducers that you can reuse for any resource slice. If you know how to write a reducer, then you know how to write a plugin.

## Using a Plugin

You define plugins for each resource type when you call [`resourceReducer`](/api-reference/resource-reducer). The second argument to that function is an `options` option, and within it you can pass `plugins` as an array:

```javascript
import resourceReducer from 'redux-resource';
import somePlugin from './some-plugin';
import anotherPlugin from './another-plugin';

export default resourceReducer('books', {
  plugins: [somePlugin, anotherPlugin]
});
```

## Writing a Plugin

A plugin is a function that with the following signature:

```javascript
(resourceType, options) => reducerFunction
```

Where `resourceType` and `options` are the arguments that you passed to [`resourceReducer`](/api-reference/resource-reducer).

The return value, `reducerFunction`, is also a function. This returned function has the same signature as a Redux reducer:

```javascript
(previousState, action) => newState
```

where `state` is the value of the state after running it through the built-in reducer and `action` is the action that was dispatched.

The simplest plugin then (which doesn't do anything), would look like this:

```javascript
function myPlugin(resourceType, options) {
  return function(state, action) {
    return state;
  }
}
```

If you prefer using arrow functions, you might choose to write this like so:

```javascript
const myPlugin = (resourceType, option) => (state, action) => state;
```

This plugin isn't very exciting, so let's look at more realistic examples.

## Selecting Resources

Let's build a plugin that lets a user select resources. The code for this plugin looks like this:

```javascript
import { setResourceMeta } from 'redux-resource';
import myActionTypes from './my-action-types';

export default function(resourceType, options) {
  return function(state, action) {
    // Ignore actions that were dispatched for another resource type
    if (action.resourceType !== resourceType) {
      return state;
    }

    if (action.type === myActionTypes.SELECT_RESOURCES) {
      return {
        ...state,
        meta: setResourceMeta({
          resources: action.resources,
          meta: state.meta,
          newMeta: {
            selected: true
          },
          initialResourceMeta: options.initialResourceMeta
        })
      };
    } else if (action.type === myActionTypes.UNSELECT_RESOURCES) {
      return {
        ...state,
        meta: setResourceMeta({
          resources: action.resources,
          meta: state.meta,
          newMeta: {
            selected: false
          },
          initialResourceMeta: options.initialResourceMeta
        })
      };
    } else {
      return state;
    }
  }
}
```

You would then use this plugin like so:

```javascript
import { createStore, combineReducers } from 'redux';
import { resourceReducer } from 'redux-resource';
import selectResources from './plugins/select-resources';

let store = createStore(
  combineReducers({
    books: resourceReducer('books', {
      plugins: [selectResources]
    }),
  })
);
```

## Customizable Plugins

You can write plugins that can be customized per-slice by taking advantage of the fact that the `resourceReducer`'s options are passed into plugins. For instance, if you had a plugin like the following:

```javascript
export default function customizablePlugin(resourceType, options) {
  return function(state, action) {
    if (options.useSpecialBehavior) {
      // Perform a computation
    } else {
      // Do some other computation here
    }
  };
}
```

then you could trigger the special behavior by passing `useSpecialBehavior: true` as an option to `resourceReducer`:

```javascript
import resourceReducer from 'redux-resource';
import customizablePlugin from './customizable-plugin';

export default resourceReducer('books', {
  plugins: [customizablePlugin],
  useSpecialBehavior: true
});
```

If this API isn't to your liking, then you can also just wrap the plugin itself in a function, like so:

```javascript
export default function(pluginOptions) {
  return function customizablePlugin(resourceType, options) {
    return function(state, action) {
      if (pluginOptions.useSpecialBehavior) {
        // Perform a computation
      } else {
        // Do some other computation here
      }
    };
  };
}
```

which would be used in the following way:

```javascript
import resourceReducer from 'redux-resource';
import customizablePlugin from './customizable-plugin';

export default resourceReducer('books', {
  plugins: [
    customizablePlugin({ useSpecialBehavior: true})
  ]
});
```

You may dislike this approach due to the tripley-nested functions. That's fine, because either way works. Use the version that makes the most sense to you.

## Best Practices

Because plugins are so similar to reducers, you can use a `switch` statement and support multiple action types within each plugin. This is usually a good thing, but be mindful of keeping each plugin limited to a single responsibility.

For example, in the above example of a plugin for selecting resources, it supports two Action types – one for selection, and one for deselection. This plugin encapsulates that one responsibility, and it isn't responsible for any other Action types.

We recommend having a plugin for each distinct *responsibility*.


# Migration Guides

On occasion, we release breaking changes to the libraries. This page links to various migration guides.

## redux-resource

* [v2 ⇨ v3](https://github.com/jamesplease/redux-resource/blob/master/packages/redux-resource/docs/migration-guides/2-to-3.md)
* [`resourceful-redux` ⇨ `redux-resource`](https://github.com/jamesplease/redux-resource/blob/master/packages/redux-resource/docs/migration-guides/1-to-2.md)

## redux-resource-xhr

* [v3 ⇨ v4](https://github.com/jamesplease/redux-resource/blob/master/packages/redux-resource-xhr/docs/migration-guides/3-to-4.md)
* [v2 ⇨ v3](https://github.com/jamesplease/redux-resource/blob/master/packages/redux-resource-xhr/docs/migration-guides/2-to-3.md)

## redux-resource-prop-types

* [v3 ⇨ v4](https://github.com/jamesplease/redux-resource/blob/master/packages/redux-resource-prop-types/docs/migration-guides/3-to-4.md)
* [v2 ⇨ v3](https://github.com/jamesplease/redux-resource/blob/master/packages/redux-resource-prop-types/docs/migration-guides/2-to-3.md)

## redux-resource-plugins

* [v2 ⇨ v3](https://github.com/jamesplease/redux-resource/blob/master/packages/redux-resource-plugins/docs/migration-guides/2-to-3.md)

## redux-resource-action-creators

* [v1 ⇨ v2](https://github.com/jamesplease/redux-resource/blob/master/packages/redux-resource-action-creators/docs/migration-guides/1-to-2.md)


# Recipes

These are patterns and snippets of code that will help you when using Redux Resource in an application. They assume that you understand the topics in the [resources](/resources) and [requests](/requests) sections of the documentation.

* [Forms](/recipes/forms)
* [Canceling Requests](/recipes/canceling-requests)
* [Unauthorized Responses](/recipes/unauthorized-responses)
* [User Feedback](/recipes/user-feedback)
* [Related Resources](/recipes/related-resources)
* [Caching](/recipes/caching)


# Forms

Redux Resource complements, but does not replace, form libraries. If you're already using a form library, we encourage you to continue using it alongside Redux Resource.

## Recommendations

The following are two popular forms libraries for Redux:

* [react-redux-form](https://github.com/davidkpiano/react-redux-form)
* [redux-form](https://github.com/erikras/redux-form)

Using component state for form data is also worth considering. However you decide to manage your form data, it should work well alongside Redux Resource.

## Using Resource Slices

You can also store form information inside of the resource slice. A Redux best practice is to separate your client-side data from your server-side data, so form information should be kept separate from the actual resource objects themselves.

Instead, you might choose to use [`meta`](/resources/meta) for form information, or perhaps an additional "top-level" key within the resource slice, such as `forms`.

One thing to consider before going with this approach is whether or not your form allows a user to modify more than one resource at a time. If it does, then you may want to consider storing the form data outside of an individual resource slice.


# Canceling Requests

Many applications transfer data using HTTP requests. One feature of HTTP requests is that they can be cancelled.

As a rule of thumb, for each request that you make in your application, there will always be one situation where you will want to cancel that request to prevent bugs.

## Why do it

Canceling requests prevents race conditions. A race condition occurs when you have two requests in flight at the same time, but your code is written such that one must resolve before the other. As you may know, requests can resolve in any order, which leads to the bugs.

A common pattern we've seen in Redux applications is this:

1. whenever a request completes, an action is dispatched
2. a reducer responds to that action, updating the state
3. a view renders using the latest data from the state

This pattern isn't bad – it's great! You just need to be aware that it can lead to bugs when requests aren't cancelled.

Let's look at two examples that demonstrate the problem.

### Example: A Typeahead

Consider a "typeahead" component that allows a user to type to search for books. Even when the user's input is debounced, there are situations where two (or more) active requests can be in flight. The user can type, wait a moment for a request to send, then type one key to fire off a second request. If the backend response time is slower than the debounce time, then two search requests will be in flight at once.

Because the requests can complete in any order, it is possible that the user's earliest search results will return *after* their latest search results. If your code is written such that the last-received search results are displayed, then that can lead to the wrong search results being shown.

Canceling a previous request resolves this problem, as it means that only one search request will ever be in flight at a time, and it will be the user's most recent search. If you're using an action creator that returns a native XMLHttpRequest object, such as the action creator from [Redux Resource XHR](/extras/redux-resource-xhr), then your code may look like this:

```javascript
class Typeahead extends Component {
  searchBooks: function(query) {
    if (this.searchBooksRequest) {
      this.searchBooksRequest.abort();
    }

    this.searchBooksRequest = this.props.searchBooks(query);
  }
}
```

Another tip is to cancel any requests when the component unmounts. If the search results aren't needed when the component unmounts, then letting a request complete will still update your state tree, which can cause unnecessary renders in your application. Canceling requests in `componentWillUnmount` might look something like:

```javascript
class Typeahead extends Component {
  componentWillUnmount: function() {
    if (this.searchBooksRequest) {
      this.searchBooksRequest.abort();
    }
  }
}
```

### Example: Pagination

Consider a page of an application that displays books. Often, long lists of resources will be paginated, and a user can move between the pages by clicking a "next" or "previous" button.

A race condition can occur when the user clicks the buttons too fast, or when the backend service is slow. If your view layer renders out the results of the latest response, then it's possible that they could see the results from the wrong page.

Similar to the search example above, ensuring that only a single page of data is being fetched at once is the solution.

The solution is the same as the typeahead example:

1. cancel any existing page-change requests before starting a new one
2. consider if it makes sense to cancel the request when the component

   unmounts

A common feature of these bugs is that they depend on unreliable network conditions, so they don't usually come up in a development environment. This makes them easy to ignore, but they're still worth protecting against.

## How to do it

Typically, applications do not need to inform the user when a request is aborted. Accordingly, Redux Resource does not track if a request is in an aborted state. Instead, we encourage you to set the request status back to `"IDLE"` when the request is canceled.

For a read request, this may look something like:

```javascript
import { actionTypes } from 'redux-resource';

// You will need to determine that the request was aborted;
// different libraries have different systems for doing this
let requestWasAborted;

if (requestWasAborted) {
  dispatch({
    type: actionTypes.READ_RESOURCES_IDLE,
    ...otherActionAttributes
  })
}
```

> Note: If your application requires tracking the aborted status of a request, you can write a [plugin](https://github.com/jamesplease/redux-resource/tree/d9d5593c6cca37810b2013cf3ba22f4ae7941910/docs/other-guides/plugin.md) to add support for additional action types.
>
> Note: We understand that some users want their action type names to reflect the action that is being performed, rather than the result of the action. We agree that this is a good practice to follow. If you do, too, it may irritate you that there is no `READ_RESOURCES_ABORT` action type. This is omitted in an effort to keep the surface area of Redux Resource small, since that action would behave the same as `READ_RESOURCES_IDLE`.

## Canceling requests in popular libraries

There are many different tools developers use to make requests. In this section, we will go through how to cancel requests using some of the most common tools.

### XMLHttpRequest

In browsers, the native way to cancel a request is to call the `abort` method on an [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest).

```javascript
const myRequest = new XMLHttpRequest();
myRequest.open('GET', 'books');

myRequest.abort();
```

### xhr

The [xhr](https://github.com/naugtur/xhr) library simplifies the creation of XHR objects. Because it returns a native XMLHttpRequest object, canceling requests with `xhr` is the same as when you use the native XMLHttpRequest constructor.

```javascript
import xhr from 'xhr';

const request = xhr.get('/books/23', (err, res) => {
  if (req.aborted) {
    console.log('Request cancelled');
  }
});

request.abort();
```

[Redux Resource XHR](/extras/redux-resource-xhr) for Redux Resource uses [`xhr`](https://github.com/naugtur/xhr) for requests. The action creator exported by this library returns a native XHR object, so you can use the `abort` method to cancel those requests.

### fetch

The native [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) method is a tool for making requests that returns a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). Native Promises cannot be cancelled ([yet](https://developer.mozilla.org/en-US/docs/Web/API/AbortController)), but you can get around this limitation by "ignoring" the server response.

One way to do this is to create a function that you return from your action creators. Then, only fire the "success" action as long as that function is not called.

Although there are benefits to actually canceling the request, this solution will avoid the race condition bugs described in this guide.

### axios

[axios](https://github.com/mzabriskie/axios) is a Promise-based approach to HTTP requests that supports cancellation. It uses a system of canceling Promises called "Cancel Tokens," which is based off of [a withdrawn cancelable Promises proposal](https://medium.com/@benlesh/promise-cancellation-is-dead-long-live-promise-cancellation-c6601f1f5082).

To see how to cancel axios requests, refer to [the axios documentation](https://github.com/mzabriskie/axios#cancellation).

### Bluebird

[Bluebird](http://bluebirdjs.com/) is Promise implementation that supports cancellation using an `onCancel` method.

Refer to [the Bluebird documentation](http://bluebirdjs.com/docs/api/cancellation.html) for specifics on the `onCancel` method.

### Observables in RxJS

[RxJS](http://reactivex.io/rxjs/) is a Reactive Programming library for async code using Observables. It includes [`Observable.ajax()`](https://chrisnoring.gitbooks.io/rxjs-5-ultimate/content/operators-and-ajax.html) for HTTP requests and supports cancellation by calling `subscription.unsubscribe()`, or using something like [`.takeUntil()`](http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-takeUntil).

If you happen to be using redux-observable, refer to that library's documentation for [a recipe for request cancellation](https://redux-observable.js.org/docs/recipes/Cancellation.html).

## Alternatives

You don't always need to cancel requests. Two other options are:

1. Prevent the user from performing an action more than once. For instance, in the search example, you could prevent the user from typing if a search of theirs is already in flight. And in the pagination example, you can disable the "next" and "previous" buttons until the new page loads. In these examples, this approach is clearly a subpar experience, but sometimes it does make sense. For instance, disabling a "Delete" button for a book once the user clicks it once, or disabling a "Buy" button after the user confirms a purchase.
2. You could write code to keep track of which request's response is the correct one to display. We generally find it to be simpler to cancel requests instead.

There may be other options, too, and different approaches may make more sense to you based on the situation.


# Unauthorized Responses

Some applications log users out after a certain period of time. For single page apps, this usually presents itself as requests to the backend suddenly failing for the logged-out user. This can occur when the user leaves the application open in their browser over night, for instance.

A common UX pattern is to display a notification to the user when this occurs, so that they can log back in. This recipe describes one way that you can detect when a user is logged out, so that you can notify them however you see fit.

## Your server

The backend that you interface with needs to provide a consistent representation of the user being logged out.

If your API uses proper [HTTP status codes](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes), then this means that the responses will have a `401` status code.

The rest of this guide will assume that the backend returns a `401` HTTP status code, although this same system works for other representations, too.

## Action Creators

Whenever an unauthorized response from the backend is returned in your CRUD action creators, include the status code in the [request action](/requests/request-actions) that you dispatch.

You can attach arbitrary data to a request by specifying `requestProperties` on the action.

If you're using [Redux Resource XHR](/extras/redux-resource-xhr), then this will be set for you. You can access the status code at `action.requestProperties.statusCode`.

If you're not using Redux Resource XHR, then your code may look something like:

```javascript
export function readBook(id) {
  return function(dispatch) {
    dispatch({
      type: actionTypes.READ_RESOURCES_PENDING,
      resourceType: 'books',
      resources: [id]
    });

    // `request` would be whatever function you are using to make HTTP
    // requests. It could be `window.fetch()`, axios, superagent, xhr,
    // or anything else that you prefer.
    request('/some-url', (err, res) => {
      // Different libraries attach the status code to different properties.
      // It is usually either `res.status` or `res.statusCode`. You do not
      // need to check both properties if you know which one your library uses.
      if (err || res.statusCode >= 400 || res.status >= 400) {
        dispatch({
          type: actionTypes.READ_RESOURCES_FAILED,
          resourceType: 'books',
          resources: [id],
          requestProperties: {
            statusCode: res.statusCode
          }
        });

        return;
      }

      // Check to see if the request was cancelled, or if it succeeded, then
      // dispatch the appropriate action here.
    });
  }
}
```

## Reducer

The final step is to write a reducer that updates the state tree whenever these failed actions occur. Here is an example reducer that does this:

```javascript
import { actionTypes } from 'redux-resource';

const {
  READ_RESOURCES_FAILED,
  UPDATE_RESOURCES_FAILED,
  CREATE_RESOURCES_FAILED,
  DELETE_RESOURCES_FAILED
} = actionTypes;

export default function reducer(state = false, action) {
  const isFailedAction = action.type === READ_RESOURCES_FAILED ||
    action.type === UPDATE_RESOURCES_FAILED ||
    action.type === CREATE_RESOURCES_FAILED ||
    action.type === DELETE_RESOURCES_FAILED;

  if (isFailedAction && action.requestProperties.statusCode === 401) {
    return true;
  }

  return state;
}
```

Before an unauthorized response has been received, this reducer will return a state of `false`. When a logged-out response is received, then the reducer will update the state to be `true`.

You'll want to use this reducer with [`combineReducers`](http://redux.js.org/docs/api/combineReducers.html):

```javascript
import { combineReducers } from 'redux';
import unauthorizedReducer from './unauthorized-reducer';

const reducer = combineReducers({
  unauthorized: unauthorizedReducer,
  // ...other store slices (your resource reducers, etc.)
});
```

With this in place, you have a slice of your state tree that will be `true` whenever an unauthorized response is received.

You can use this value in your view layer to toggle the appearance of a modal, or some other notification, to let the user know that they need to log back in.


# User Feedback

It's important to provide a user with feedback of the status of network requests. When applications don't provide good request feedback, users will lose confidence in the app. You may have experienced this first hand if you've ever clicked a button within an application, and then thought to yourself, "Did that work?"

You don't want to create those negative experiences, and when you use Redux Resource, you have all of the information you need to create good ones instead.

In this recipe, we will cover some tips for providing good feedback to your user around requests. Think of these tips as guidelines, rather than rules set in stone. Different applications require different user experiences.

## Pending Requests

You should visually communicate to the user anytime that a request is in flight. This lets them know that the application is processing the operation.

The [`getStatus`](/api-reference/get-status) method returns an object with a `pending` property, which will be `true` whenever the associated request is in flight. You can use this to show a spinner, for instance. If you're using React, this might look like:

```jsx
render() {
  const { state } = this.props;
  const readStatus = getStatus(state, 'books.meta[24].readStatus');

  return (
    <div>
      {readStatus.pending && (<Spinner/>)}
    </div>
  );
}
```

A spinner is a common pattern for indicating that an operation is underway, but it doesn't work in every situation. For instance, you might know that the request will take awhile, such as large file uploads. In those situations, it might make sense to use a different element, such a a progress bar, to represent the progress of the request.

Regardless of how you communicate the loading state, loading indicators should be unobtrusive. Some applications will overlay the whole interface, or a large section of the interface, with a spinner whenever an action occurs. This prevents the user from taking any other action with the page while also hindering their ability to read content on the page. This is a bad user experience.

In many situations, a better approach is to display a loading indicator near to the affected elements on the page. For instance, if the user is deleting a resource from a list of resources, then perhaps it makes sense for a spinner to be displayed next to the delete button that they clicked. This prevents the spinner from interfering with other, unrelated elements on the page.

### Disabling Interface Elements

Sometimes, it makes sense to disable elements of an interface when a CRUD request is in flight. Always take a minimalist approach when it comes to disabling interface elements: disable as little as possible.

Typically, if a user clicks a button to initiate a request, then you will want to disable that button so that they don't submit multiple requests at the same time.

Some example buttons that you should consider disabling are:

* a delete button. It doesn't make sense for two delete requests to be in flight at the same time.
* a payment button
* a "save" button to save their changes to a resource

Sometimes, developers go too far when they disable interface elements. For instance, some applications cover the entire page, or a large portion of the page, with a loading indicator. This prevents the user from interacting with a large portion of the page, which is a poor user experience.

If you're using React, an example code snippet of disabling a button is:

```jsx
render() {
  const { state } = this.props;
  const deleteStatus = getStatus(state, 'books.meta[24].deleteStatus');

  return (
    <div>
      <button disabled={deleteStatus.pending}>
        Delete Book
      </button>
    </div>
  );
}
```

## Failed Requests

When a request fails, there should be a human-readable message that states that the request was unsuccessful. Unless your users are developers, error codes probably won't be helpful to users. A message that simply says "There was an error with your request." can provide a better user experience than one that says "Error code 2603," even though it *technically* contains less information.

I don't mean to convey that error codes aren't useful. They can be! Especially in logs and diagnostics. But always ask yourself if it makes sense to display them to the user.

If you're able to convert an error code into a more specific, human-readable message (like "You must provide an email address."), then that's even better.

In addition to an explanatory message, it sometimes makes sense to provide the user with a link to attempt the operation again as part of the message. In React, a typical error message might look like the following:

```jsx
render() {
  const { state } = this.props;
  const readStatus = getStatus(state, 'books.meta[24].readStatus');

  return (
    <div>
      {readStatus.failed && (
        <div>
          <span>
            There was an error fetching the book.
          </span>
          <button onClick={this.fetchBook}/>
            Retry.
          <button>
        </div>  
      )}
    </div>
  );
}
```

An even better UI would distinguish between different error types. Why was there an error? Did the network request fail because the user lost their internet connection? Did they get logged out? Did some form data fail server-side validation?

You can store information about the error on the response object to provide an even better user experience.

### Unauthorized Responses

Some applications expire a user's session after a period of time. When that occurs, the user won't be able to perform any CRUD operations until they log back in.

There is [a recipe](/recipes/unauthorized-responses) that provides you with a Boolean that is `true` whenever this happens. Once you have that value, you can let the user know that they've been logged out.

One way to do this would be to open a modal letting them know what happened, and what they need to do. You can even make the modal have one button, "Log in again." If you choose to use this method, be considerate of the fact that a user may have been inputting data into a form. If you interrupt their workflow like this, it's wise to save their work into local storage, and let them know that when they log in, the information that they've entered won't be lost.

If you're using React, the code to do this may look like the following:

```jsx
render() {
  const { unauthorized } = this.props;

  return (
    <div>
      {unauthorized && (<LoggedOutModal/>)}
    </div>
  );
}
```

## Successful Requests

Users typically know when a read request succeeds because the data that was fetched is displayed in the interface. For other requests, such as updating a resource or deleting a resource, you should consider providing some other indicator.

Some examples of indicators include:

* A toast or notification that appears, stating that the operation succeeded.
* Text appearing on the interface, stating that the request succeeded. This approach is frequently seen on account and settings pages when changes are made.
* If a spinner is used for the loading state, it could be transformed into a green checkmark, indicating success.

This list is not meant to be exhaustive; there are many other ways to indicate success.

Success indicators follow a similar pattern to the other indicators if you're using React. For instance:

```jsx
render() {
  const { state } = this.props;
  const updateState = getStatus(state, 'books.meta[24].updateStatus');

  return (
    <div>
      {updateState.succeeded && ('Your settings have been updated')}
    </div>
  );
}
```


# Related Resources

Endpoints frequently return more than one resource type in a single response. For instance, a request for a single `author` may also include the author's `books`.

Because different backends return related resources in many different ways, Redux Resource couldn't possibly include a single built-in solution that works for every API. Instead, [plugins](/other-guides/custom-action-types) can be used to support related resources in a way that works for your specific backend.

The rest of this guide will describe supporting related resources for the following technologies:

* [normalizr](/recipes/related-resources#normalizr)
* [JSON API](/recipes/related-resources#json-api)
* [GraphQL](/recipes/related-resources#graphql)

> Would you like us to include a guide for a technology not listed here? Just [open an issue](https://github.com/jamesplease/redux-resource/issues/new?title=related%20resource%20plugin\&body=I%27d%20like%20to%20see%20a%20related%20resource%20guide%20for%20a%20new%20technology)!

## normalizr

The [Included Resources Plugin](/extras/redux-resource-plugins/included-resources-plugin) works well with [normalizr](https://github.com/paularmstrong/normalizr) data. Refer to the Included Resources Plugin documentation to familiarize yourself with its API.

Here's an example demonstrating using Redux Resource with normalizr on a slice that has the Included Resources Plugin:

```javascript
import { normalize, schema } from 'normalizr';
import store from './store';

const user = new schema.Entity('users');

const comment = new schema.Entity('comments', {
  commenter: user
});

const article = new schema.Entity('articles', {
  author: user,
  comments: [comment]
});

const originalData = [{
  id: '123',
  author: {
    id: '1',
    name: 'Paul'
  },
  title: 'My awesome blog post',
  comments: [
    {
      id: '324',
      commenter: {
        id: '2',
        name: 'Nicole'
      }
    }
  ]
}];

const normalizedData = normalize(originalData, [article]);

const action = {
  type: actionTypes.READ_RESOURCES_SUCCEEDED,
  // We recommend that you use the same string for the `resourceType`, resource slice,
  // and normalizr key.
  resourceType: article.key,
  resources: normalizedData.result,
  includedResources: normalizedData.entities
};

store.dispatch(action);
```

If you're using the [`redux-resource-xhr`](/extras/redux-resource-xhr) library, you can perform this normalization in the `onSucceeded` callback:

```javascript
import { crudRequest } from 'redux-resource-xhr';
import { normalize } from 'normalizr';
import authorSchema from './schema';

export function readAuthor(authorId) {
  const xhrOptions = {
    method: 'GET',
    url: `/authors/${authorId}`,
    json: true
  };

  return dispatch => crudRequest('read', {
    dispatch,
    xhrOptions,
    actionDefaults: {
      resourceType: 'authors',
      resources: [authorId]
    },
    onSucceeded(action, res, body) {
      const normalizedData = normalize(body, authorSchema);

      dispatch({
        ...action,
        includedResources: normalizedData.entities
      });
    }
  });
}
```

## JSON API

At the moment, the easiest way to support JSON API compound documents is to use the [jsonapi-normalizr](https://github.com/maxatwork/jsonapi-normalizr) library, and then follow the normalizr guide above.

An official JSON API plugin is being [planned](https://github.com/jamesplease/redux-resource/issues/38). We would love your help!

If you would like to try your hand at writing a JSON API relationship plugin, here are a few tips. In short, you would need to interpet the `included` member of a [compound document](http://jsonapi.org/format/#document-compound-documents). This would likely work in 2 steps:

1. Filter the Array of `included` resources to find *just* the resources whose

   JSON API `type` matches the `resourceType` of the slice.
2. Use [`upsertResources`](/api-reference/upsert-resources) to add those resources to the slice.

You would also want to place the each individual resource's `meta` into the `meta` section of the slice.

## GraphQL

We would love to support GraphQL, but we need your help. If you're interested in helping out, please [open an issue](https://github.com/jamesplease/redux-resource/issues/new?title=GraphQL%20plugin\&body=I%27m%20interested%20in%20helping%20out%20with%20a%20GraphQL%20plugin) to chat about it. Thank you!


# Caching

Caching server responses can improve the responsiveness of your application.

Because the main Redux Resource library does not provide tools to make HTTP requests, it is not possible for the main library to provide a caching mechanism.

With that said, bindings for view libraries, such as React, are the perfect place for caching to be implemented. Official React bindings for Redux Resource are in the works, and they will be built using [React Request](https://github.com/jamesplease/react-request), a powerful, declarative HTTP library for React.

This recipe contains tips that could help you if you're interested in writing your own caching implementation, either by using React Request or by writing your own system.

## Caching using requests

How can you know if a response has already been returned for a given request? The way that we recommend doing it is by using [request objects](/requests/request-objects).

Here's how it works with React Request:

React Request implements its own [caching system](https://github.com/jamesplease/react-request/blob/master/docs/guides/response-caching.md). Its caching is powered by a string called a ["request key"](https://github.com/jamesplease/react-request/blob/master/docs/guides/request-keys.md) based on the request configuration you pass to it. Two requests with the same key are considered identical.

This automatically-generated "request key" will be used as the Redux Resource requestKey, which is what ties the two libraries together.

## Accessing data from a dynamic key

Tools like `getStatus` are more difficult to use directly when using a dynamic request name.

In the official React bindings for Redux Resource, the solution to this problem will be a wrapping component *around* React Request will automatically pull the details of that request from the Redux store, and pass it to you in a render prop function. It will also pull the resources, resource meta, and lists that the request affected.

Because of this, you will rely a lot less on directly using `getStatus` and `getResources` when using React Redux Resource, although they will still be there should you need them.

## The role of lists

Sometimes, requests contribute to a list. For instance, if you fetch a user's favorite books, and then they create a new favorite book, you may have a list called `"favoriteBooks"`, which is what your component renders out.

What do you do in this situation? Simply continue to cache at the request level.

By using a cached response, you are making the claim that a response from the server for that request could not provide any more information for the list that you already have.

As a result, you do not make the request, and you continue to render out the locally-cached list.


# Ecosystem Extras

The Redux Resource ecosystem provides bits of code that make working with the library even better.

* [Redux Resource Action Creators](/extras/redux-resource-action-creators)
* [Redux Resource XHR](/extras/redux-resource-xhr)
* [Redux Resource Plugins](/extras/redux-resource-plugins)
* [Redux Resource Prop Types](/extras/redux-resource-prop-types)


# Redux Resource Action Creators

[![npm version](https://img.shields.io/npm/v/redux-resource-action-creators.svg)](https://www.npmjs.com/package/redux-resource-action-creators) [![gzip size](http://img.badgesize.io/https://unpkg.com/redux-resource-action-creators/dist/redux-resource-action-creators.min.js?compression=gzip)](https://unpkg.com/redux-resource-action-creators/dist/redux-resource-action-creators.min.js)

This library makes it more convenient to create valid [request actions](/requests/request-actions). It helps out in two ways:

1. Remembering the [request action types](/api-reference/action-types) can be difficult
2. Often times, your "start" and "end" actions share many properties, and it can feel like unnecessary

   boilerplate to copy + paste those properties

Unlike [Redux Resource XHR](/extras/redux-resource-xhr), these action creators do not make the requests for you. All this library does is create the actions themselves.

## Other Guides

**Old Documentation**

* [1.x documentation](https://github.com/jamesplease/redux-resource/blob/master/packages/redux-resource-action-creators/docs/old-versions/1.md)

**Migration Guides**

* [v1 to v2](https://github.com/jamesplease/redux-resource/blob/master/packages/redux-resource-action-creators/docs/migration-guides/1-to-2.md)

## Installation

Install `redux-resource-action-creators` from npm:

`npm install redux-resource-action-creators --save`

Then, import `createActionCreators` in your application:

```javascript
import createActionCreators from 'redux-resource-action-creators';
```

## Usage

This library has a single export, `createActionCreators`.

## `createActionCreators( crudAction, actionDefaults )`

### Arguments

1. `crudAction`: *(String)* The CRUD operation being performed. One of "create", "read", "update", or "delete". This determines the [CRUD Action types](/api-reference/action-types) that are dispatched.
2. `actionDefaults` *(Object)*: Properties that will be included on each dispatched action. The [Request Action guide](/requests/request-actions) lists possible options, such as `resourceType` and `resources`. You *must* include `resourceType`.

### Returns

(*`Object`*): An object with four methods: `pending`, `succeeded`, `failed`, and `idle`. These action creators return actions for you, based on the action properties that you provide to them.

### Example

```javascript
import createActionCreators from 'redux-resource-action-creators';
import store from './store';

const readActionCreators = createActionCreators('read', {
  resourceType: 'books',
  requestKey: 'getHomePageBooks',
  list: 'homePageBooks',
  mergeListIds: false
});

store.dispatch(readActionCreators.pending());

const req = fetchData((err, res, body) => {
  if (req.aborted) {
    store.dispatch(readActionCreators.idle());
  } else if (err) {
    store.dispatch(readActionCreators.failed());
  } else {
    store.dispatch(readActionCreators.succeeded({
      resources: body
    }));
  }
});
```

To understand why you might use this library, compare that example versus this common Redux Resource code:

```javascript
import { actionTypes } from 'redux-resource';
import store from './store';

store.dispatch({
  type: actionTypes.READ_RESOURCES_PENDING,
  resourceType: 'books',
  requestKey: 'getHomePageBooks',
  list: 'homePageBooks'
});

const req = fetchData((err, res, body) => {
  if (req.aborted) {
    store.dispatch({
      type: actionTypes.READ_RESOURCES_NULL,
      resourceType: 'books',
      requestKey: 'getHomePageBooks',
      list: 'homePageBooks'
    });
  } else if (err) {
    store.dispatch({
      type: actionTypes.READ_RESOURCES_FAILED,
      resourceType: 'books',
      requestKey: 'getHomePageBooks',
      list: 'homePageBooks'
    });
  } else {
    store.dispatch(readActionCreators.succeeded({
      type: actionTypes.READ_RESOURCES_SUCCEEDED,
      resourceType: 'books',
      requestKey: 'getHomePageBooks',
      list: 'homePageBooks',
      resources: body
    }));
  }
});
```

All that this library does is provides a simple pattern to write less, more expressive code. If you'd like, you could get many of the same benefits by defining shared action properties, and then spreading them in your actions:

```javascript
import { actionTypes } from 'redux-resource';
import store from './store';

const actionDefaults = {
  resourceType: 'books',
  requestKey: 'getHomePageBooks',
  list: 'homePageBooks'
};

store.dispatch({
  ...actionDefaults,
  type: actionTypes.READ_RESOURCES_PENDING,
});

const req = fetchData((err, res, body) => {
  if (req.aborted) {
    store.dispatch({
      ...actionDefaults,
      type: actionTypes.READ_RESOURCES_NULL,
    });
  } else if (err) {
    store.dispatch({
      ...actionDefaults,
      type: actionTypes.READ_RESOURCES_FAILED,
    });
  } else {
    store.dispatch(readActionCreators.succeeded({
      ...actionDefaults,
      type: actionTypes.READ_RESOURCES_SUCCEEDED,
      resources: body
    }));
  }
});
```


# Redux Resource XHR

[![npm version](https://img.shields.io/npm/v/redux-resource-xhr.svg)](https://www.npmjs.com/package/redux-resource-xhr) [![gzip size](http://img.badgesize.io/https://unpkg.com/redux-resource-xhr/dist/redux-resource-xhr.min.js?compression=gzip)](https://unpkg.com/redux-resource-xhr/dist/redux-resource-xhr.min.js)

Redux Resource XHR is an action creator that simplifies CRUD operations.

More information about CRUD actions in Redux Resource can be found in the [Request Actions](/requests/request-actions) guide and the four guides on CRUD:

* [Reading resources](/requests/request-actions/reading-resources)
* [Updating resources](/requests/request-actions/updating-resources)
* [Creating resources](/requests/request-actions/creating-resources)
* [Deleting resources](/requests/request-actions/deleting-resources)

We recommend familiarizing yourself with the content in those guides before using this library.

## Other Guides

**Old Documentation**

* [2.x documentation](https://github.com/jamesplease/redux-resource/blob/master/packages/redux-resource-xhr/docs/old-versions/2.md)
* [3.x documentation](https://github.com/jamesplease/redux-resource/blob/master/packages/redux-resource-xhr/docs/old-versions/3.md)

**Migration Guides**

* [v2 to v3](https://github.com/jamesplease/redux-resource/blob/master/packages/redux-resource-xhr/docs/migration-guides/2-to-3.md)
* [v3 to v4](https://github.com/jamesplease/redux-resource/blob/master/packages/redux-resource-xhr/docs/migration-guides/3-to-4.md)

## Installation

Install `redux-resource-xhr` from npm:

`npm install redux-resource-xhr --save`

Then, import the `crudRequest` action creator in your application:

```javascript
import { crudRequest } from 'redux-resource-xhr';
```

## Usage

This library has two exports: an action creator for CRUD operations, `crudRequest`, and the library used for making the HTTP requests, [`xhr`](/extras/redux-resource-xhr#xhr-options-).

## `crudRequest( crudAction, options )`

An action creator for CRUD requests.

### Arguments

1. `crudAction`: *(String)* The CRUD operation being performed. One of "create", "read", "update", or "delete". This determines the [CRUD Action types](/api-reference/action-types) that are dispatched.
2. `options` *(Object)*: Options to configure the CRUD request.
   * `actionDefaults`: *(Object)* Properties that will be included on each dispatched action. All of [the Request Action options](/requests/request-actions) are supported, such as `resourceType` and `resources`.
   * `dispatch`: *(Function)* The `dispatch` function of a Redux store. If you're using [`redux-thunk`](https://github.com/gaearon/redux-thunk), this will be the first argument of the thunk.
   * `xhrOptions`: *(Object)* Options to pass to the [`xhr`](/extras/redux-resource-xhr#xhr-options-) library. You must pass an `url` (or `uri`) option. You will typically also want to pass `json: true`, which will serialize your request body into JSON, as well as parse the response body as JSON. For more, see the examples below and [the xhr documentation](https://github.com/naugtur/xhr).
   * \[`transformData`]: *(Function)* An optional function to transform the data received by the server. It receives one argument, `body`, which is the response from the server, parsed as JSON. Return a transformed list of `resources`. This can be used to format the server response into a Redux Resource-compatible format. For more, see the guide on [Resource objects](/resources/resource-objects).
   * \[`onPending`]: *(Function)* An optional function that allows you to modify the "pending" action, as well as control when it is dispatched. It is called with one argument: `action`. When this function is provided, you will be responsible for dispatching the action.
   * \[`onAborted`]: *(Function)* An optional function that allows you to modify the "aborted" action, as well as control when it is dispatched. It is called with arguments `(action, res)`. When this function is provided, you will be responsible for dispatching the action.
   * \[`onFailed`]: *(Function)* An optional function that allows you to modify the "failed" action, as well as control when it is dispatched. It is called with arguments `(action, err, res)`. When this function is provided, you will be responsible for dispatching the action.
   * \[`onSucceeded`]: *(Function)* An optional function that allows you to modify the "succeeded" action, as well as control when it is dispatched. It is called with arguments `(action, res, body)`. When this function is provided, you will be responsible for dispatching the action.

     If all that you need to do is transform the resources that your backend returns, then you should use `transformData` instead of `onSuceeded`.

### Returns

(*`XMLHttpRequest`*): An instance of a [`XMLHttpRequest`](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest). Typically, you'll use this object to abort the request (should you need to) by calling `myXhr.abort()`.

### Example

```javascript
import { crudRequest } from 'redux-resource-xhr';
import store from './store';

const xhrOptions = {
  method: 'GET',
  json: true,
  url: '/books',
  qs: {
    user: 'someone@example.com'
  }
};

const xhr = crudRequest('read', {
  dispatch: store.dispatch,
  actionDefaults: {
    resourceType: 'books',
    requestKey: 'getHomePageBooks',
    list: 'homePageBooks',
    mergeListIds: false
  },
  xhrOptions
});

// Cancel the request if you need to
xhr.abort();
```

## `xhr( options )`

This is the library used to make HTTP requests. It is a thin wrapper around the library [`xhr`](https://github.com/naugtur/xhr), and supports all of the same options and signatures.

On top of that, it adds several new features:

1. Support for query string serialization (similar to the [`request`](https://github.com/request/request#requestoptions-callback) library).
2. Omitting the callback will return a native [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).

### Customizing Query String Serialization

If you pass a `qs` object, then the object will be serialized into a query parameter using the [`querystringify`](https://www.npmjs.com/package/querystringify) library. This library supports basic serialization, but we don't expect it to work for every API that you interface with.

You can change how the query string is serialized using two options:

* `qsStringify` - a function with the signature `(qs, options)`. It should return the string to be appended to the URI.
* `qsStringifyOptions` - an object that is passed as the second argument to the `qsStringify` method.

For instance, if you wish to use the `qs` library, you might do this:

```javascript
import { xhr } from 'redux-resource-xhr';
import qs from 'qs';

xhr('/books', {
  method: 'GET',
  qs: {
    pageSize: 10,
    pageNumber: 0,
    publishers: ['goldenBooks', 'penguinBooks']
  },
  qsStringify: qs.stringify,
  qsStringifyOptions: { arrayFormat: 'brackets' }
}, cb);
```

### Example

```javascript
import { xhr } from 'redux-resource-xhr';

const booksSearch = xhr.get('/books', {
  // Pass a `qs` option, and it will be stringified and appended to the URL
  // for you
  qs: {
    bookName: 'brilliance of the moon'
  },
  json: true
}, (err, res, body) => {
  console.log('Got some books', body);
});

// Later, you can abort the request:
booksSearch.abort();

// Omit a callback to get a native Promise. This can be useful sometimes, but the
// tradeoff is that you cannot cancel Promises.
xhr.get('/books/24')
  .then(
    (res) => console.log('got a book', res),
    (err) => console.log('there was an error', err)
  );
```

## Tips

* The `onSucceeded` option of `crudRequest` can be useful if your backend returns [related resources](https://github.com/jamesplease/redux-resource/tree/7ddb5bb28b9219710af7e01fdd70d60447782cc4/docs/extras/docs/recipes/related-resources.md) in a single request.
* The `onSucceeded` and `onFailed` options can also be used for chaining requests. You can make a second (or third, or fourth!) HTTP request in these callbacks. This is useful when you need to make multiple requests to get all of the data that your interface needs.
* A good pattern for using this collection is to make your own action creators that "wrap" these action creators using [redux-thunk](https://github.com/gaearon/redux-thunk). That way, your view layer doesn't need to concern itself with all of the configuration necessary to use these action creators. For instances, an action creator for reading books in your application may look like the following:

  ```javascript
  import { crudRequest } from 'redux-resource-xhr';

  function readManyBooks({ pageNumber }) {
    return (dispatch) => {
      const xhrOptions = {
        method: 'GET',
        json: true,
        url: '/books',
        qs: { pageNumber }
      };

      return crudRequest('read', {
        actionDefaults: {
          resourceType: 'books',
          requestKey: 'getHomePageBooks',
          list: 'homePageBooks',
          mergeListIds: false,
        },
        xhrOptions,
        dispatch
      });
    };
  }
  ```

  Then, in your view layer, you can call `readManyBooks({ pageNumber: 5 })`.


# Redux Resource Prop Types

[![npm version](https://img.shields.io/npm/v/redux-resource-prop-types.svg)](https://www.npmjs.com/package/redux-resource-prop-types) [![gzip size](http://img.badgesize.io/https://unpkg.com/redux-resource-prop-types/dist/redux-resource-prop-types.min.js?compression=gzip)](https://unpkg.com/redux-resource-prop-types/dist/redux-resource-prop-types.min.js)

A collection of [prop-types](https://github.com/facebook/prop-types) objects.

## Other Guides

**Old Documentation**

* [2.x documentation](https://github.com/jamesplease/redux-resource/blob/master/packages/redux-resource-prop-types/docs/old-versions/2.md)
* [3.x documentation](https://github.com/jamesplease/redux-resource/blob/master/packages/redux-resource-prop-types/docs/old-versions/3.md)

**Migration Guides**

* [v2 to v3](https://github.com/jamesplease/redux-resource/blob/master/packages/redux-resource-prop-types/docs/migration-guides/2-to-3.md)
* [v3 to v4](https://github.com/jamesplease/redux-resource/blob/master/packages/redux-resource-prop-types/docs/migration-guides/3-to-4.md)

## Installation

Install `redux-resource-prop-types` with npm:

`npm install redux-resource-prop-types --save`

Then, import the prop types that you need:

```javascript
import { resourcesPropType } from 'redux-resource-prop-types';
```

## Usage

If you're using React, refer to the [Typechecking with PropTypes](https://facebook.github.io/react/docs/typechecking-with-proptypes.html) guide on how to use the exported prop types. If you're not using React, refer to the documentation of the [prop-types](https://github.com/facebook/prop-types) library.

We recommend using the prop types in this library to build your own prop types, which you can reuse throughout your application.

### `idPropType`

Validates a single resource ID.

> Tip: This prop type requires that your IDs be either strings or numbers.

```javascript
import PropTypes from 'prop-types';
import { idPropType } from 'redux-resource-prop-types';

MyComponent.propTypes = {
  selectedBookIds: PropTypes.arrayOf(idPropType).isRequired
};

mapStateToProps(state) {
  return {
    selectedBookIds: state.books.selectedIds
  };
}
```

### `statusPropType`

Validates the object returned by [`getStatus`](/api-reference/get-status).

```javascript
import { getStatus } from 'redux-resource';
import { statusPropType } from 'redux-resource-prop-types';

MyComponent.propTypes = {
  booksReadStatus: statusPropType
};

mapStateToProps(state) {
  return {
    bookReadStatus: getStatus(state, 'books.meta[23].readStatus');
  };
}
```

### `requestStatusPropType`

Validates that a value is one of the [`requestStatuses`](/api-reference/request-statuses). Typically, you'll want to use `statusPropType` instead, but this can be useful when verifying the structure of your slice.

```javascript
import { requestStatusPropType } from 'redux-resource-prop-types';

MyComponent.propTypes = {
  bookRequestStatus: requestStatusPropType
};

mapStateToProps(state) {
  return {
    bookRequestStatus: state.books.meta[23].readStatus
  };
}
```

### `resourcePropType`

Validates a resource. Similar to `PropTypes.shape()`, except that it enforces an ID.

```javascript
import PropTypes from 'prop-types';
import { resourcePropType } from 'redux-resource-prop-types';

MyComponent.propTypes = {
  book: resourcePropType({
    name: PropTypes.string.isRequired,
    releaseYear: PropTypes.number.isRequired
  })
};

mapStateToProps(state) {
  return {
    book: state.books.resources[23]
  };
}
```

### `requestPropType`

Validates a [request object](/requests/request-objects). Similar to `PropTypes.shape()`, except that it enforces `ids`, `status`, `requestKey` and `resourceType`. Typically, you won't need to use this, but it can be useful to verify the structure of your state.

```javascript
import PropTypes from 'prop-types';
import { requestPropType } from 'redux-resource-prop-types';

MyComponent.propTypes = {
  searchRequest: requestPropType({
    statusCode: PropTypes.number.isRequired
  })
};

mapStateToProps(state) {
  return {
    searchRequest: state.books.requests.search
  };
}
```


# Redux Resource Plugins

[![npm version](https://img.shields.io/npm/v/redux-resource-plugins.svg)](https://www.npmjs.com/package/redux-resource-plugins) [![gzip size](http://img.badgesize.io/https://unpkg.com/redux-resource-plugins/dist/redux-resource-plugins.min.js?compression=gzip)](https://unpkg.com/redux-resource-plugins/dist/redux-resource-plugins.min.js)

These plugins can be used to augment the reducer returned by `resourceReducer`. The plugins are a collection of common patterns that you may find yourself needing when writing a CRUD application.

Do you find yourself using the same plugin over and over? [Let us know](https://github.com/jamesplease/redux-resource/issues/new?title=New+plugin+suggestion), and it might find its way into this package!

## Other Guides

**Old Documentation**

* [2.x documentation](https://github.com/jamesplease/redux-resource/blob/33a79cfdddb0dc5dae10f7073ece28e90dbd1455/docs/extras/redux-resource-plugins.md)

**Migration Guides**

* [v2 to v3](https://github.com/jamesplease/redux-resource/blob/master/packages/redux-resource-plugins/docs/migration-guides/2-to-3.md)

## Installation

Install `redux-resource-plugins` from npm:

`npm install redux-resource-plugins --save`

Then, import the pieces of the package that you need:

```javascript
import { selection } from 'redux-resource-plugins';
```

## Usage

This library is a collection of different plugins. Refer to their individual documentation pages to learn more.

* [`reset`](/extras/redux-resource-plugins/reset-plugin): This plugin provides action types that let you reset the state of an entire slice. You can also pass a list to reset the state of just that list.
* [`includedResources`](/extras/redux-resource-plugins/included-resources-plugin): This plugin adds support for including multiple resource types into a single action for read requests. This can be useful if you're using GraphQL, JSON API, or normalizr.
* [`httpStatusCodes`](/extras/redux-resource-plugins/http-status-codes-plugin): Add this plugin to track the HTTP status codes associated with each request. The built-in reducer behavior doesn't provide any information specific to HTTP. What this means is that if a request fails, for instance, you won't be able to tell that it failed with a 404 response.

### Deprecated Plugins

The following plugins are deprecated. There are built-in features that provide the same functionality as these plugins.

* [`selection`](/extras/redux-resource-plugins/selection-plugin): This plugin allows you to

  maintain a list of "selected" resource IDs. If your interface displays a list

  of resources that the user can select to perform bulk operations on, then this

  might be useful to you.


# HTTP Status Codes

## Documentation

Add this plugin to keep track of status codes of your HTTP Requests on resource metadata. This is useful because status codes give you more detail information about your in-flight requests.

Note that you can simply use [request objects](/requests/request-objects) instead of this plugin. For instance:

```javascript
dispatch({
  type: 'READ_RESOURCES_FAILED',
  resourceType: 'books',
  requestKey: 'searchBooks',
  requestProperties: {
    statusCode: 404
  }
});

// => resource object:
//
// {
//   requestKey: 'searchBooks',
//   status: 'FAILED',
//   statusCode: 404
// }
```

This plugin is only useful when you specifically want to track the status on resource metadata.

## Usage

First, you need to register this plugin when you call [`resourceReducer`](/api-reference/resource-reducer).

```javascript
import { resourceReducer } from 'redux-resource';
import { httpStatusCodes } from 'redux-resource-plugins';

const reducer = resourceReducer('books', {
  plugins: [httpStatusCodes]
});
```

This plugin doesn't come with any custom action types. Instead, it changes the way the state is tranformed with the built-in CRUD [action types](/api-reference/action-types). Any time that you pass a `statusCode` in an action with one of those types, then the code will be stored in your state tree.

Passing the status code looks like the following:

```javascript
import { actionTypes } from 'redux-resource';
import store from './store';

store.dispatch({
  type: actionTypes.READ_RESOURCES_FAILED,
  resourceType: 'books',
  resources: [10],
  statusCode: 404
});
```

If you're using the [Redux Resource XHR](/extras/redux-resource-xhr) library, then you don't need to do anything differently: request status codes are already included in the actions dispatched from that library.

Within your resource metadata, the status code will be available at one of four keys, depending on the CRUD operation being performed:

* `createStatusCode`
* `readStatusCode`
* `updateStatusCode`
* `deleteStatusCode`

On a request object, the code is just available under `statusCode`.

```javascript
import store from './store';

const state = store.getState();

// Access the status codes of some resource meta
const bookStatusCode = state.books.meta[24].readStatusCode;

// Access the status code from a request object
const searchStatusCode = state.books.requests.search.statusCode;
```


# Selection

## Documentation

Use this plugin to maintain a list of "selected" resources within a slice. This is useful for interfaces that let users select a subset of resources to perform a bulk CRUD operation on.

For instance, consider the app that you use for email. You may be able to select multiple emails, and then mark them all as read. This plugin can help with a feature like this.

This plugin is limited to supporting a single list. If you need support for multiple lists, then you may want to use the [`UPDATE_RESOURCES` action type](/resources/modifying-resources) to modify lists directly instead.

Here is an example action creator that replaces the `selectResources` action type:

```javascript
function selectResources(resourceType, ids) {
  return {
    type: 'UPDATE_RESOURCES',
    resources: {
      [resourceType]: {
        selected: ids
      }
    }
  };
}
```

You can build similar action creators for `deselectResources` and `clearSelectedResources`.

> Note: For some historical context, the selection plugin was created before Redux Resource included support for the `UPDATE_RESOURCES` action.

## Usage

First, you need to register this plugin for any slice that needs it. This plugin adds an additional property to your slice, `selectedIds`, so it comes with initial state that you should add to the slice, too.

```javascript
import { resourceReducer } from 'redux-resource';
import { selection } from 'redux-resource-plugins';

const reducer = resourceReducer('books', {
  initialState: {
    ...selection.initialState
  },
  plugins: [selection]
});
```

Then, you can use the action creators that ships with the plugin to manage the selected resources.

```javascript
import { selection } from 'redux-resource-plugins';
import store from './store';

// Select resources with ID "24" and ID "100"
store.dispatch(selection.selectResources('books', [24, 100]));

// Deselect resources with ID "24" and ID "100"
store.dispatch(selection.deselectResources('books', [24, 100]));

// Clear all of the selected books
store.dispatch(selection.clearSelectedResources('books'));
```

You can also pass resource objects. Just make sure that they have an ID!

```javascript
// Selects books with ID 24 and 100
store.dispatch(selection.selectResources('books', [
  { id: 24, title: 'My Name is Red' },
  100
]));
```

To access the selected resources, you can use code that might look something like the following:

```javascript
import store from './store';

const books = store.getState().books;

// Access the selected resources directly
const selectedBooks = books.selectedIds.map(id => books.resources[id]);
```

Or, you could pass the selected IDs into an action creator to perform a bulk operation.

```javascript
import { deleteBooks } from './books/action-creators';
import store from './store';

const books = store.getState().books;

// Initiate an action to delete all of the selected books
deleteBooks(books.selectedIds);
```

## `selectResources(resourceType, resources)`

Selects `resources` for slice `resourceType`. Resources that are already selected will be ignored.

### Arguments

1. `resourceType` *(String)*: The name of the slice to select resources from.
2. `resources` *(Array)*: An array of resources, or resource IDs, to be selected.

### Returns

(`Object`): A Redux action.

## `deselectResources(resourceType, resources)`

Deselects `resources` for slice `resourceType`. Resources that aren't selected will be ignored.

### Arguments

1. `resourceType` *(String)*: The name of the slice to deselect resources from.
2. `resources` *(Array)*: An array of resources, or resource IDs, to deselect.

### Returns

(`Object`): A Redux action.

## `clearSelectedResources(resourceType)`

Deselects every resource for slice `resourceType`.

### Arguments

1. `resourceType` *(String)*: The name of the slice to clear the selected

   resources from.

### Returns

(`Object`): A Redux action.

## Tips

* Whenever you delete resources, you will want to make sure that you manually

  deselect them.


# Reset

The reset plugin allows you to remove all of the data in a slice, effectively "resetting" it. You may optionally scope the resetting to affect a single [list](/resources/lists) or [request object](/requests/request-objects).

## Usage

First, you need to register this plugin for any slice that needs it.

```javascript
import { resourceReducer } from 'redux-resource';
import { reset } from 'redux-resource-plugins';

const reducer = resourceReducer('books', {
  plugins: [reset]
});
```

Then, you can use the action creator that ships with the plugin to perform the reset.

```javascript
import { reset } from 'redux-resource-plugins';
import store from './store';

store.dispatch(reset.resetResource('books'));
```

Resetting a slice will leave you with the following state:

```javascript
{
  resources: {},
  meta: {},
  lists: {},
  requests: {}
}
```

Resetting a list will set the list to be an empty array.

The additional initial state that you pass to `resourceReducer` will also be included when you reset your state.

You can pass a second argument, `options`, to scope what is reset:

```javascript
import { reset } from 'redux-resource-plugins';
import store from './store';

// Reset just the "createBook" request
store.dispatch(reset.resetResource('books', {
  requestKey: 'createBook'
}));

// Reset just the "favorites" list
store.dispatch(reset.resetResource('books', {
  list: 'favorites'
}));

// Reset a list and a request at the same time
store.dispatch(reset.resetResource('books', {
  list: 'favorites',
  requestKey: 'readFavorites'
}));
```

## `resetResource(resourceType, [options])`

Resets the slice for `resourceType`. Pass `options` to scope what's reset. There are two valid options:

* `requestKey`: Reset the request with this key
* `list`: Reset the list with this name

### Arguments

1. `resourceType` *(String)*: The name of the slice to reset.
2. \[`options`] *(String)*: Options to scope what is reset.

### Returns

(`Object`): A Redux action to be dispatched.


# Included Resources

APIs frequently support returning multiple resource types in a single request. For instance, an endpoint may allow you to fetch an author as well as that author's books. In this example, `authors` and `books` are two different resource types.

This plugin is designed to allow you to dispatch a single action that includes multiple types. It is optimized to receive normalized data, such as what is returned from [`normalizr`](https://github.com/paularmstrong/normalizr).

## Usage

Add this plugin when you call [`resourceReducer`](/api-reference/resource-reducer). Be sure to add it to the "primary" resource slice, as well as to the included resource slices.

```javascript
import { resourceReducer } from 'redux-resource';
import { includedResources } from 'redux-resource-plugins';

const authorReducer = resourceReducer('authors', {
  plugins: [includedResources]
});

const booksReducer = resourceReducer('books', {
  plugins: [includedResources]
});
```

This plugin doesn't come with any custom action types. Instead, it changes the way the state is transformed with the built-in successful create, update or read CRUD [action type](/api-reference/action-types): `CREATE_RESOURCES_SUCCEEDED`, `UPDATE_RESOURCES_SUCCEEDED` and `READ_RESOURCES_SUCCEEDED`.

When your actions have an `includedResources` object, they will be added to the appropriate slices.

An example of using `includedResources` is the following:

```javascript
import { actionTypes } from 'redux-resource';
import store from './store';

store.dispatch({
  type: actionTypes.READ_RESOURCES_SUCCEEDED,
  resourceType: 'authors',
  resources: [{
    id: 10,
    name: 'Sarah'
  }],
  includedResources: {
    // Resources are key'd off by their name.
    // The value can be an Object or an Array.

    // Here we pass books as an Object. `normalizr` returns
    // a shape like this.
    books: {
      23: {
        id: 23,
        name: 'Some book'
      },
      100: {
        id: 50,
        name: 'Another book'
      }
    },

    // Notice here that comments is an Array. This format works, too.
    comments: [
      {
        id: 23,
        name: 'Great author!'
      },
      {
        id: 100,
        name: 'One of my favorite authors'
      }
    ]
  }
});
```

Be sure to use `includedResources` on *every* resource slice that can appear in `includedResources`. In the above example, we would want to include the plugin for our `authors`, `books`, and `comments`.

This plugin will respect the `mergeResources` and `mergeMeta` action properties.

## Related Reading

Not every API returns included resources in a normalized manner, so a different plugin may be more appropriate for certain backends. As an example, JSON API does not provide included resources in a format that can be interpreted by this plugin.

For more on this subject, refer to the [Related Resources recipe](/recipes/related-resources).


# FAQ

* [General](/faq/general)
* [State Tree](/faq/state-tree)
* [Actions](/faq/actions)
* [Lists](/faq/lists)


# General

### When should I use Redux Resource?

If you feel that you're writing too much boilerplate when using Redux by itself, then it might be worth giving a library like Redux Resource a try. There are [similar projects](/introduction/similar-projects) that also aim to reduce Redux boilerplate, which are also worth your consideration.

### Does this only work with React?

No. The only requirement is that you are using Redux, or a library that has a similar API to Redux.

### How does this library handle immutable state?

This library uses shallow cloning for state tree updates. This has worked well for us, even on medium-to-large sized applications.

Redux Resource does not work well with libraries like [Immutable.js](https://facebook.github.io/immutable-js/), although we're open to adding support for Immutable if it doesn't bloat the library too much. If this is something you're interested in, [open an issue](https://github.com/jamesplease/redux-resource/issues/new) and we can talk more about it.

### Does this only work with APIs that return data in a specific format?

No, this library is agnostic to the format that you receive data in. The only requirement is that each resource that you pass into this library has an `id` attribute.

We understand that not every system stores its resources with an `id` attribute. For instance, if you're working with a books resource, then it might instead have an id attribute called `bookId`. In these situations, you will need to write a transform that maps that key to be `id` instead.

For more, refer to [the Resource objects guide](/resources/resource-objects).

### Does this work with a backend that adheres to a well-defined format, such as JSON API?

Yes, it does. You may want to write a [plugin](/other-guides/custom-action-types) to handle some advanced features provided by specifications such as JSON API, such as rich relationship support.

### Does this work with backends that are not strictly "RESTful"?

Yes. The only requirement is that the data returned can be reasonably mapped to the concept of a "resource." A resource, from this library's perspective, is a JavaScript object with an `id` attribute.

For more on this, refer to [the Resource objects guide](/resources/resource-objects).

### Does Redux Resource handle forms, or client-side changes to data?

This library complements, but does not replace, solutions for managing forms and other ways to manipulate resource data on the client. Redux Resource works well with any system for managing forms, such as view state, [react-redux-form](https://github.com/davidkpiano/react-redux-form), or [redux-form](https://github.com/erikras/redux-form).

### Why does `getStatus` take the entire state as the first argument, while `getResources` takes a slice?

`getResources` always returns one subset of resources of a single type, so it wouldn't make sense to pass the entire state as the first argument. When aggregating request statuses, you may need to aggregate across multiple slices, so it's a requirement that `getStatus` support that.

In older versions of Redux Resource, `getResources` accepted `state` as the first argument. The problem with this approach is that it really only worked well when you were using `combineReducers`. Although we believe that most people are likely using `combineReducers`, we didn't want that to be a hard requirement for using Redux Resource.

## What is the area that needs the most improvement in the Redux Resource API?

There should be an API that does the following, all at once:

1. Makes network requests (while also handling caching and request deduplication for you)
2. Places resources into the store
3. Makes those resources available to you in your Components

With React Hooks, this might look like:

```jsx
function BookComponent({ bookId }) {
  const books = useResources(() => fetchBooks({ bookId }));

  return (
    <div>
      {/* Render this component using the `books` resources */}
    </div>
  )
}
```

Right now, the process of doing these 3 steps is unnecessarily verbose using the out-of-the-box Redux Resource API.

Note that there is nothing about the API that prevents you from writing your code like this. It is just that the library does not provide this API for you, and it should.

This is the biggest improvement that we would like to make to the API.


# State Tree

## Can I store additional metadata for resources within `meta`?

You can, and we encourage it. We recommend that you avoid changing the values of the request statuses directly (use the built-in Action types to do this), but feel free to store anything else in there that you want.

You can use the `UPDATE_RESOURCES` action type to change the metadata of resources.

If you'd like to update metadata alongside a request, then you can write a [plugin](/other-guides/custom-action-types) for that.

A future version of Redux Resource will support this without a plugin.

## Can I store additional properties on each state slice?

Yes, you can. The only requirement is that you don't change the structure of the state that you start out with: make sure that `resources`, `meta`, `lists`, and `requests` remain Objects. If you stick with that you shouldn't run into any issues.

As a convention, we recommend only storing data relevant to the resource in the slice. Use another slice for other information.

## Can I store more than one resource per state slice?

We don't recommend doing this.


# Actions

## Are there Action Creators?

Not in the core library.

When it comes to making requests, there is an [HTTP Action Creators library](/extras/redux-resource-xhr).

Developers have different preferences when it comes to making requests, so we made this library easy to use with any library that you choose. We've had great success with the library linked to above, but should you choose to write your own, we have guides to help you.

Refer to the [Request Actions](/requests/request-actions) guide to learn more about how to build your own action creator, or the four CRUD guides for examples of action creators:

* [Reading resources](/requests/request-actions/reading-resources)
* [Updating resources](/requests/request-actions/reading-resources)
* [Creating resources](/requests/request-actions/reading-resources)
* [Deleting resources](/requests/request-actions/reading-resources)

## Does Redux Resource require you to use a specific tool for making HTTP requests?

No, you can use any system for making requests that you'd like. We do strongly encourage you to use a library that supports [cancellation](/recipes/canceling-requests).

## Should all Actions include a request key?

If you're manually coming up with the request keys, then it is typically extra boilerplate to *always* use them. In those situations, we recommend only using request keys when they provide you value.

Because request keys are used to make request objects within the store, anytime that you need a request object is when you should use a request key. The two most common use cases for request objects are:

1. creating resources
2. multiple bulk reads of the same resource type on the same page

If you're not doing either of those things, then you might not need to name the request, and that's fine.

A handy rule of thumb for when to use request objects, as well as much more information about requests, can be found in [Request Keys and Names guide](https://github.com/jamesplease/redux-resource/tree/bde4ba22af7a4611903b51557ba2300eb7b2397d/docs/requests/keys-and-names.md#when-to-use-request-keys).

## When is setting the `mergeMeta` action attribute to `false` useful?

At the moment, we don't know of any use case for doing this. We included this attribute in the event that you find one – we're sure there's one out there!


# Lists

## How can you keep a list in order?

Redux Resource currently only provides lists as a way to keep track of the initial sort order returned from a single request. As more requests are made against a single list, it will not respect any particular order.

If you'd like to maintain ordering of some kind within a specific list, or all of your lists, then we recommend [writing a plugin](/other-guides/custom-action-types) to handle that.

## Can lists be used for keeping track of client-side lists of resources?

Yes, they can. Use the `UPDATE_RESOURCES` action type to manage client-side things.

## How do you know when to use dynamically-named lists or not?

In the majority of situations, you won't need to use dynamic lists. For instance, if you are building a banking application that lets a user display transactions for each of their bank accounts, you might think to make a list for each one, like this:

`transactionsFor${accountId}`

There are situations when this could be useful. For instance, if you wish to display the transactions of many bank accounts onscreen at once. Most applications, though, only let the user see one set of transactions per account at once. Therefore, it's much better to just use a single list.

`transactionsForAccount`

As the user moves between pages in the application, you can set `mergeListIds` to `false` to throw away the previous list, and start fresh.

Concerned about caching? That should be handled at the request level instead. Check out [the caching recipe](/recipes/caching) for more.

If you need animations, then you may consider using dynamic lists or a solution like [freezus](https://github.com/threepointone/freezus) to "freeze" the state of the outgoing component.

## Why is `mergeListIds` set to `true` in request actions by default?

There are a few reasons.

1. It's nice that all of the `mergeX` attributes of the CRUD actions are `true` by default.
2. Multiple requests can contribute to a list. For instance, a user may read a list of

   favorites, and then create a new favorite. In this situation, we have multiple requests

   contributing to the same list, so it's good that the resources are merged, rather than

   replaced.

We understand that `mergeListIds` is one of those attributes that you'll frequently be setting to false. We believe the reasons above justify keeping it `true` by default, but if you disagree, feel free to [open an issue](https://github.com/jamesplease/redux-resource/issues/new?title=mergeListIds+defaults+to+true) and we'd be happy to discuss it further with you!


# API Reference

## Top-Level Exports

* [resourceReducer](/api-reference/resource-reducer)
* [getStatus](/api-reference/get-status)
* [getResources](/api-reference/get-resources)
* [upsertResources](/api-reference/upsert-resources)
* [setResourceMeta](/api-reference/set-resource-meta)
* [actionTypes](/api-reference/action-types)
* [requestStatuses](/api-reference/request-statuses)

## Importing

Every function or object described above is a top-level export. You can import any of them like this:

### ES6

```javascript
import { resourceReducer } from 'redux-resource';
```

### ES5 (CommonJS)

```javascript
var resourceReducer = require('redux-resource').resourceReducer;
```


# resourceReducer

Creates a Redux [reducer](http://redux.js.org/docs/basics/Reducers.html) that manages a [resource slice](/introduction/core-concepts).

## Arguments

1. `resourceType` *(String)*: The type of your resource. Typically, you'll want to use a plural type. For instance, "books," rather than "book." When using [combineReducers](http://redux.js.org/docs/api/combineReducers.html), you should also use this as the key of your store slice for consistency.
2. \[`options`] *(Object)*: Options that can be used to configure the reducer. The options are:
   * `initialState`: Initial state to shallowly merge into the default initial state for the slice of the store.
   * `plugins`: An array of reducer functions that will be called after the default reducer function. Use this to augment the behavior of the built-in reducer, or to add support for custom action types for this store slice. Plugins are functions that are called with the arguments `(state, action, options)`, where `options` are the same options that you passed to `resourceReducer`. For more, refer to the [Plugins](/other-guides/custom-action-types) documentation.
   * `initialResourceMeta`: Additional metadata to include on any new resource's metadata after a read or create operation.

## Returns

([`Reducer`](http://redux.js.org/docs/basics/Reducers.html)): A reducing function for this resource.

## Example

```javascript
import { createStore, combineReducers } from 'redux';
import { resourceReducer } from 'redux-resource';

let store = createStore(
  combineReducers({
    books: resourceReducer('books'),
    users: resourceReducer('users')
  })
);
```

## Tips

* Any options you pass to the `resourceReducer` will also be passed to the

  plugins. You can use this fact to add your own custom `options` to

  configure the behavior of your plugins. To learn more about plugins, refer

  to [the Plugins guide](/other-guides/custom-action-types).


# getStatus

Returns an object with boolean values representing the request status of a particular CRUD operation. It can also be used to aggregate multiple request statuses together.

## Arguments

1. `state` *(Object)*: Typically, the current state of the Redux store, but more generally it can be any object that has a request status somewhere deeply nested within it.
2. `statusLocation` *(String|Array)*: A single path that points to a request status within `state`. If you pass an array of status locations, then they will be aggregated. For more on status locations and status aggregation, see the Notes below.
3. \[`treatIdleAsPending`] *(Boolean)*: Whether or not a request status of `IDLE` is to be considered as a `pending` request. Defaults to `false`. See Tips on when to use this.

## Returns

(*`Object`*): An Object representing the status of this request for the statusLocation. It has the following shape:

```javascript
  {
    idle: Boolean,
    pending: Boolean,
    failed: Boolean,
    succeeded: Boolean
  }
```

Only one of these values is always `true`, reflecting the value of the request status. When `treatIdleAsPending` is `true`, then request statuses that are `"IDLE"` will be returned as `pending: true`.

## Notes

* Passing an array of status locations as the second argument will aggregate the statuses. The aggregation works as follows:
  * If all of the requests are idle, then the aggregate status is idle
  * If *any* of the requests are failed, then the aggregate status is failed.
  * If no requests have failed, but some are pending, then the aggregate status is pending.
  * If all requests have succeeded, then the aggregate status is succeeded.
* A status location is a string that specifies a location of a request status in your state tree. For instance `"books.meta.24.readStatus"` or `"books.requests.dashboardSearch.status"`.

> Keep in mind that `treatIdleAsPending` also works when aggregating.

## Examples

In this example, we pass a single status location:

```javascript
import { getStatus } from 'redux-resource';
import store from './store';

const state = store.getState();
const bookDeleteStatus = getStatus(state, 'books.meta[23].deleteStatus');
```

In this example, we pass two locations:

```javascript
import { getStatus } from 'redux-resource';
import store from './store';

const state = store.getState();
const bookReadStatus = getStatus(
  state,
  [
    'articles.meta[23].readStatus',
    'comments.requests.detailsRead.status'
  ],
  true
);
```

## Tips

* The third argument, `treatIdleAsPending`, is useful for requests that are made when your components mount. The components will often render before the request begins, so the status of these requests will be `IDLE`. Passing `treatIdleAsPending` will consider these `IDLE` states as `pending: true`.
* If you're using React, we recommend computing your `getStatus` values in `mapStateToProps`, and then passing them in as props into your component. That way, you have access to this information in all of the lifecycle methods of your component.
* The first argument, `state`, doesn't always need to be the state of your Redux store. For instance, if you're using this method within your component's lifecycle methods, such as `componentDidUpdate`, you may instead pass it an object that is a subset of the state. This can be useful when you're comparing a previous status against the current status.


# getResources

Returns an array or object of resources from `resourceSlice` based on the `filter` provided.

### Arguments

1. `resourceSlice` *(Object)*: The slice of your state that a `resourceReducer` is responsible for.
2. `filter` *(Array|String|Function)*: The filter to apply. It can be an array of resource IDs, or the name of a [list](/resources/lists). If a function is provided, then `getResources` will iterate over the collection of resources, returning the resources that the function returns truthy for. The function will be called with three arguments: `(resource, resourceMeta, resourceSlice)`. If no `filter` is provided, then all of the resources in the `resourceSlice` will be returned.
3. `options` *(Object)*: An object to customize the behavior of `getResources`. Presently, only one option is supported: `byId`. Pass `{ byId true }` to receive the results as an object instead of an array.

### Returns

(*`Array|Object`*): An Array of resources, unless `byId` is passed as true, in which case an object will be returned instead.

### Example

```javascript
import { getResources } from 'redux-resource';
import store from './store';

const state = store.getState();

// Retrieve resources by an array of IDs
const someBooks = getResources(state.books, [1, 12, 23]);

// Retrieve those same resources as an object
const someBooksAsObject = getResources(state.books, [1, 12, 23], { byId: true });

// Retrieve resources by a list name
const popularBooks = getResources(state.books, 'mostPopular');

// Retrieve the "selected" resources
const selectedBooks = getResources(state.books, (resource, meta) => meta.selected);

// Returns all resources
const allResources = getResources(state.books);
```

## Tips

* You don't *always* need to use this method to access resources. Just need one resource? If the resource is on a slice called `books`, you can directly access it using `store.getState().books.resources[bookId]`.
* When the order of your resources doesn't matter, then it probably makes sense to pass `{ byId: true }` as `options` so that you can look up your resources more quickly.


# upsertResources

Add new or update existing resources in your state tree.

## Arguments

1. `resources` *(Object)*: The current resources object from your state tree.
2. `newResources` *(Array|Object)*: The new resources to add or update.
3. \[`mergeResources`] *(Boolean)*: Whether or not to merge individual resources with the existing resource in the store, or to replace it with the new data. Defaults to `true`.

## Returns

(`Object`): The updated resources object.

## Example

```javascript
import { upsertResources } from 'redux-resource';
import actionTypes from './my-action-types';

export default function reducer(state, action) {
  switch (action.type) {
    case (actionTypes.CREATE_RESOURCES_CUSTOM): {
      const newResources = upsertResources({
        resources: state.resources,
        newResources: action.resources
      });

      return {
        ...state,
        resources: newResources
      };
    }
  }
}
```

## Tips

* This is used internally within the reducer returned by

  [`resourceReducer`](/api-reference/resource-reducer) to add and update resources in the

  store. You will typically only need to use this function if you're authoring a

  [plugin](/other-guides/custom-action-types).


# setResourceMeta

Update one or more individual resources with the same metadata.

## Arguments

1. `options` *(Object)*: An object that defines how to update the metadata. The options are as follows:
   * `resources` *(Array|Object)*: An array of the resources, or resource IDs, to update with the new meta.
   * `newMeta` *(Object)*: The meta to set on each of the resources.
   * `meta` *(Object)*: The current resource meta object from this resource's store slice. Optional when `mergeMeta` is `false`, required otherwise.
   * \[`initialResourceMeta`] *(Object)*: Additional metadata to add to any resource that previously did not have meta.
   * \[`mergeMeta`] *(Boolean)*: Whether or not to merge a resource's old metadata with the new metadata. Defaults to `true`.

## Returns

(`Object`): The new resource meta object.

## Example

```javascript
import { setResourceMeta } from 'redux-resource';
import actionTypes from './my-action-types';

export default function reducer(state, action) {
  switch (action.type) {
    case (actionTypes.SELECT_MANY_RESOURCES): {
      const meta = setResourceMeta({
        resources: action.resources,
        meta: state.meta,
        newMeta: {
          selected: true
        }
      });

      return {
        ...state,
        meta
      };
    }
  }
}
```

## Tips

* This is used internally within the reducer returned by

  [`resourceReducer`](/api-reference/resource-reducer) to update the resource meta in your

  state tree. You will typically only need to use this method if you're writing

  a [plugin](/other-guides/custom-action-types).


# actionTypes

An object of Redux [action types](http://redux.js.org/docs/basics/Actions.html) that the [resource reducer](/api-reference/resource-reducer) responds to. Dispatch these from action creators to change the state of your store.

The complete object is shown below:

```javascript
{
  // Update resources, metadata, and lists synchronously
  UPDATE_RESOURCES: 'UPDATE_RESOURCES',
  // Remove resources from the store synchronously
  DELETE_RESOURCES: 'DELETE_RESOURCES',

  // The following action types are to support CRUD'ing resources
  // asynchronously using requests
  CREATE_RESOURCES_PENDING: 'CREATE_RESOURCES_PENDING',
  CREATE_RESOURCES_FAILED: 'CREATE_RESOURCES_FAILED',
  CREATE_RESOURCES_SUCCEEDED: 'CREATE_RESOURCES_SUCCEEDED',
  CREATE_RESOURCES_IDLE: 'CREATE_RESOURCES_IDLE',

  READ_RESOURCES_PENDING: 'READ_RESOURCES_PENDING',
  READ_RESOURCES_FAILED: 'READ_RESOURCES_FAILED',
  READ_RESOURCES_SUCCEEDED: 'READ_RESOURCES_SUCCEEDED',
  READ_RESOURCES_IDLE: 'READ_RESOURCES_IDLE',

  UPDATE_RESOURCES_PENDING: 'UPDATE_RESOURCES_PENDING',
  UPDATE_RESOURCES_FAILED: 'UPDATE_RESOURCES_FAILED',
  UPDATE_RESOURCES_SUCCEEDED: 'UPDATE_RESOURCES_SUCCEEDED',
  UPDATE_RESOURCES_IDLE: 'UPDATE_RESOURCES_IDLE',

  DELETE_RESOURCES_PENDING: 'DELETE_RESOURCES_PENDING',
  DELETE_RESOURCES_FAILED: 'DELETE_RESOURCES_FAILED',
  DELETE_RESOURCES_SUCCEEDED: 'DELETE_RESOURCES_SUCCEEDED',
  DELETE_RESOURCES_IDLE: 'DELETE_RESOURCES_IDLE',
}
```

### Notes

The action types can be organized into two groups:

* Direct manipulation of the store. `UPDATE_RESOURCES` and `DELETE_RESOURCES` allow you to synchronously modify the store, independent of requests.
* The rest of the action types are for requests. Within the request action types, there are four groups of action types, one for each of the four [CRUD](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete) actions. Within each CRUD action "group," the four action types reflect the four request statuses.

## Reserved Action Types

An upcoming version of Redux Resource will utilize four new action types to simplify the request action types. Accordingly, these action types have been reserved, and we do not recommend that you use them in your application. The list of reserved action types is:

```
REQUEST_IDLE
REQUEST_PENDING
REQUEST_FAILED
REQUEST_SUCCEEDED
```

> Note: A warning will be logged to the console if you dispatch an action with one of these action types in your application.

### Example

This example shows an action creator that reads a single book. It uses the [redux-thunk](https://github.com/gaearon/redux-thunk) middleware and the library [xhr](https://github.com/naugtur/xhr) for making requests.

```javascript
import { actionTypes } from 'redux-resource';
import xhr from 'xhr';

export default function readBook(bookId) {
  return function(dispatch) {
    dispatch({
      type: actionTypes.READ_RESOURCES_PENDING,
      resourceType: 'books'
      resources: [bookId]
    });

    const req = xhr.get(`/books/${bookId}`, {json: true}, (err, res) => {
      if (req.aborted) {
        dispatch({
          type: actionTypes.READ_RESOURCES_IDLE,
          resourceType: 'books',
          resources: [bookId]
        });
      } else if (err || res.statusCode >= 400) {
        dispatch({
          type: actionTypes.READ_RESOURCES_FAILED,
          resourceType: 'books',
          resources: [bookId]
        });
      } else {
        dispatch({
          type: actionTypes.READ_RESOURCES_SUCCEEDED,
          resourceType: 'books',
          resources: [res.body]
        });
      }
    });

    return req;
  }
}
```

### Tips

* The `{crudAction}_RESOURCES_IDLE` action type is useful anytime that you want to "reset" the status of a request. One use case for this is when a request is aborted. Another use case would be for an alert that displays whenever a request is in a failed state. When the user dismisses the alert, you might trigger this action type to 'reset' the request status back to `IDLE`, which would then hide the alert.

  You may not always use this action type, and that's fine. But it's here if you do need it.


# requestStatuses

An object that represents the four statuses that a request can have. The complete object is shown below:

```javascript
{
  IDLE: 'IDLE',
  PENDING: 'PENDING',
  FAILED: 'FAILED',
  SUCCEEDED: 'SUCCEEDED',
}
```

## Example

```javascript
import { requestStatuses } from 'redux-resource';
import store from './store';

const state = store.getState();

if (state.books.meta['23'].readStatus === requestStatuses.PENDING) {
  console.log('A book with id "23" is currently being fetched.');
}
```

## Tips

* Although this object *can* be used to check the status of a request in your

  view layer, it's often more convenient to use [`getStatus`](/api-reference/get-status)

  for that purpose. For this reason, we recommend restricting your usage of this

  object to plugins, reducers, or action creators.


