How you ever been annoyed by the amount of boilerplate which comes with communicating to the REST Api from react/redux? well this is what we are trying to solve here.
This package requires you to have setup an api that follows the REST API conventions.
In order to use this package you need to have those installed:
- react
- react-redux
- prop-types
You start by adding this package to your project
npm i redest --save-dev
or using yarn
yarn add redest
Where you define all of your reducers, you should import the reducerSetup module.
import { combineReducers } from 'redux';
import { reducerSetup } from 'redest';
export combineReducers({
redest: reducerSetup(options)
});
It is not necessary to pass an options object. Under is all the options you can pass to it
const defaultSettings = {
internalPropPrefix: '__redest__',
components: {
loading: null,
error: null,
},
requests: {
prefix: '',
retrieveRequestData: response => response.data,
retrievePaginationData: response => response._pagination,
isErrorResponse: (statusCode, response) => statusCode >= 400,
processError: error => error,
batch: {
enabled: false,
delayTimeMS: 10,
url: '/batch',
method: 'POST',
buildRequestBody: requests => {
return {
batch: requests,
};
},
parseResponse: response =>
response.map(singleResponse => ({
body: singleResponse.body,
statusCode: singleResponse.statusCode,
})),
},
},
};
This is the component we are rendering by default when loading.
This is the component we are rendering by default when there is an error.
Here you can define a prefix you want all of your requests to have. Quite normal to use /api
here.
This method is called before your response is handled. The default here assumes that the response looks like this:
{
"data": "some data"
}
It is important to return the data formated in the correct way from this function.
Should return an array of entities. It is important that all entities have an id so that we can normalize the data.
Should return an object of the entity. It is important that all entities have an id so that we can normalize the data.
Should return whatever is going to be stored
should return an object containing the pagination info of the request or be null if there is no request data. the object should look like this:
{
"total": 1,
"limit": 5
}
Total is total number of entities there is and the limit is how many entities we should display per page.
To find out if the request is successful
do whatever you need to format the error
This is so that if you make multiple request in the delayTimeMS (default 10ms) they will be sent as one request.
takes a list of requests as an argument. Each element looks like this:
{
"method": "GET",
"url": "/users",
"body": "some data"
}
It should return an object which will be sent as the request body.
Takes the response as it's only parameter. this function should return an array of object containing two elements.
body
should be whatever would have been return if it was a normal requeststatusCode
the html status code.
In order to fetch and use the data you need to wrap your component with Redest
and pass your component as the first argument and a function which takes a props
argument as the second argument. This function will from this point on be called
the selector function
. Under is an example of the Redest wrapper.
import { Redest } from 'redest';
...
export default Redest(Component, (props) => ({ users: props.match.params.id }));
this function takes a props argument so that you can decide what data you want to access. It returns an object where each entries represent data that you want to retrieve. There are multiple format supported and under are explanations on all the different types of objects you can return.
Let's say you want to retrieve all users.
{
"users": "all"
}
or
{
"users": {
"filter": "all"
}
}
This will make a GET request to /users
endpoint.
For example if you want to get all female users.
{
"users": {
"filter": {
"gender": "female"
}
}
}
This will make a GET request to /users?gender=female
endpoint.
For example if you want to get a single user.
{
"users": 1
}
or
{
"users": {
"filter": 1
}
}
This will make a GET request to /users/1
endpoint.
If you need to customize some part of the request made in redest you can do so here as well. There is three extra parameter you can pass to it. Under is what they default to internally if you do not pass them. Endpoint and reducer is calculated from the object key.
{
"users": {
"endpoint": "/users",
"reducer": "users",
"raw": false
}
}
The key of the object is used for creating the props name that Redest passes to the component.
Endpoint parameter will be used as url when making the call to your backend
The name of the reducer we are going to use internally to store the data.
Internally Redest will automatically normalize your data. This is an option to disable that.
Let's says you have setup your selector function to retrieve users
. This means
you will have a prop in your component called this.props.users
.
If you have decided to retrieve multiple users entities the this.props.users
variable will have this structure:
{
"entities": [],
"meta": {
"isLoading": false,
"loadedAt": 10923874,
"error": false,
"ids": []
}
}
If you have decided to retrieve one user the this.props.users
variable will
have this structure:
{
"entity": {},
"meta": {
"isLoading": false,
"loadedAt": 10923874,
"error": false
}
}
If you have decided to retrieve data with raw = true
the this.props.users
variable will have this structure:
{
"data": {},
"meta": {
"isLoading": false,
"loadedAt": 10923874,
"error": false
}
}
All the actions will be made available alongside the meta, entity, entities and
data object that we saw above. So let's say that you fetched all users, your
users
prop will actually look like this:
users = {
entities: [],
meta: {
isLoading: false,
loadedAt: 10923874,
error: false,
ids: [],
},
actions: {
create: data => {},
update: (id, data) => {},
remove: id => {},
invalidate: () => {},
},
};
All actions under assumes that we are working with users.
It takes one argument which is an object that contains the data you want to send
to the backend. It will automatically make a POST request to /users
endpoint.
It takes two arguments
- the id of the entity you want to Update
- the data you want to send to the backend
This endpoint will make a POST request to /users/:id
. So if the id you want to
update is 10
, it will make a request to /users/10
It takes one argument which is the id of the entity you want to remove. It will
make a DELETE request to /users/:id
This function will invalidate the cache so that we will refetch the next time the data is accessed.
Please take a look at our contribution page