Flux REST API for redux infrastructure
redux-api solves the problem of writing clients to communicate with backends. It generates actions and reducers for making AJAX calls to API endpoints. You don't need to write a lot of boilerplate code if you use redux and want to exchange data with server.
Inspired by Redux-rest and is intended to be used with Redux.
See DOCS.md for API documentation.
- AuthorizationJWT.md - example of JWT Authorization
- Scoping.md - use scoping or using multiple redux-api instance without naming intersections.
With npm:
npm install redux-api --saveWith bower:
bower install redux-api --saveIf you don't use tools like webpack, browserify, etc and you want to load redux-api manually, the best way to add redux-api to your project is:
<script src="(...)/redux-api.min.js"></script>
<script>
window.ReduxApi = window["redux-api"];
// or
var ReduxApi = window["redux-api"];
// initialization code
</script>=======
redux-api doesn't bind you to a technology to make AJAX calls. It uses configurable adapters - a pretty simple function which receives 2 arguments: endpoint and options, and returns a Promise as result. The default adapter uses isomorphic-fetch, and has an implementation like this:
function adapterFetch(url, options) {
return fetch(url, options);
}However, you are not tied to using isomorphic-fetch. For instance, if you prefer to use jQuery, you can use the following adapter:
function adapterJquery(url, options) {
return new Promise((success, error)=> {
$.ajax({ ...options, url, success, error });
});
}This implementation allows you to make any request and process any response.
And of course you have to set up adapter to your redux-api instance before using.
reduxApi(....).use("fetch", adapterFetch)
=======
api/test.js
import reduxApi, { transformers } from 'redux-api'
import fetch from 'isomorphic-fetch'
import adapterFetch from 'api/helpers/fetch'
import { getRequestHeaders } from 'api/helpers/actions'
export default reduxApi({
objects: {
url: '/webapi/v1/test/list',
options: {
method: 'GET',
},
transformer: transformers.collection,
},
createObject: {
url: '/webapi/v1/test/creator',
virtual: true,
options: {
method: 'POST',
},
transformer: transformers.object,
},
}).use('fetch', adapterFetch(fetch)).use('options', () => ({
headers: getRequestHeaders(),
}))transformers.collection: returns response or when it's undefined { items: [], meta: { ... }}
transformers.object: returns response or empty object when it's undefined
api/test.js
import reduxApi, { transformers, HASH } from 'redux-api'
import fetch from 'isomorphic-fetch'
import adapterFetch from 'api/helpers/fetch'
import { getRequestHeaders } from 'api/helpers/actions'
export default reduxApi({
test: {
url: 'http://localhost:3000/',
options: {
method: 'POST',
},
transformer: transformers.object,
composeHashFrom: [HASH.URL],
},
}).use('fetch', adapterFetch(fetch)).use('options', () => ({
headers: getRequestHeaders(),
}))composeHashFrom is an object with { URL, HEADERS, BODY } parameters. The purpose of that object is to generate hash which leads to recognize
newest request for same/similiar resource.
GET /api/test composeHashFrom - [URL] could be enough
POST /api/test/create composeHashFrom - [URL] could not be enough 'cause for example body in POST is changing every request. In that case it should be [HASH.BODY, HASH.URL]
Test.js
import React, { useEffect } from 'react'
import { connect } from 'react-redux'
import testApi from 'api/test'
const tickets = ({
test,
fetchTest,
}) => {
useEffect(() => {
for (let i = 0; i <= 20; i++) fetchTest({}, { x: i })
}, [])
return <span>{test.x}</span>
}
const mapStateToProps = state => ({
test: state.test,
})
const mapDispatchToProps = ({
fetchTest: testApi.actions.test.force,
})
export default connect(mapStateToProps, mapDispatchToProps)(tickets)