Related Resources
Endpoints frequently 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 can be used to support related resources in a way that works for for your specific backend.
The rest of this guide will describe supporting related resources for the following technologies:
Would you like us to include a guide for a technology not listed here? Just open an issue!
normalizr
The Included Resources Plugin works well with 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:
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 `resourceName`, resource slice,
// and normalizr key.
resourceName: article.key,
resources: normalizedData.result,
includedResources: normalizedData.entities
};
store.dispatch(action);
If you're using the redux-resource-xhr
library,
you can perform this normalization in the onSucceeded
callback:
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: {
resourceName: '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 library, and then follow the normalizr guide above.
An official JSON API plugin is being planned. 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. This
would likely work in 2 steps:
- Filter the Array of
included
resources to find just the resources whose JSON APItype
matches theresourceName
of the slice. - Use
upsertResources
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 to chat about it. Thank you!