
redux-rest
NOTE this requires redux 1.0.0-rc or above
NOTE POST/PUT requests currently tied to Django Rest Framework's CSRF handling and response content
Create Redux action constants, action creators and reducers for your
REST API with no boilerplate.
Install
npm install redux-rest
Example
import React from 'react';
import { connect, Provider } from 'react-redux';
import { createStore, combineReducers, applyMiddleware } from 'redux';
import thunkMiddleware from 'redux-thunk';
import API from 'redux-rest';
const myAPI = {
users: '/api/users/'
};
const api = new API(myAPI);
class UserApp extends React.component {
componentDidMount() {
this.props.dispatch(api.actionCreators.users.list());
}
render() {
let users = this.props.users;
let pendingUsers = users.filter(u => u.status === 'pending');
let currentUsers = users.filter(u => u.status !== 'pending');
return (
<div>
{pendingUsers.map(user => <p>Saving {user.username}...</p>)}
<ul>
{currentUsers.map(user => <li>{user.username}</li>)}
</ul>
<input ref="username" placeholder="Enter username"/>
<input type="submit" value="Add user" onClick={this._addUser}/>
</div>
);
}
_addUser() {
let inputNode = React.findDOMNode(this.refs.username);
let val = inputNode.value;
this.props.dispatch(
api.actionCreators.users.create(
{username: val}
)
);
inputNode.val = '';
}
}
let reducers = combineReducers(api.reducers);
let createStoreWithMiddleware = applyMiddleware(
thunkMiddleware
)(createStore);
let store = createStoreWithMiddleware(reducers);
function select(state) {
return {
users: state.users_items
};
})
UserApp = connect(select)(UserApp);
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
{() => <UserApp />}
</Provider>
);
}
}
What is the api object?
The api object encapsulates common patterns when dealing with REST APIs.
When created with a description of your API you can call all the actions you'd
expect and there are reducers that automatically handle those actions, including
'pending', 'success' and 'failure' states.
import API from 'redux-rest';
const myAPI = {
users: '/api/users/',
}
const api = new API(myAPI);
This creates a pair of reducers for each API endpoint; a collection
reducer to handle actions at the collection level and and item
reducer to handle actions on individual items.
TODO not sure about the item/collection stuff. Needs a rethink.
Calling actions is as simple as
api.actionCreators.users.create(userData);
Status of API requests
Each action creator triggers an API request and immediately dispatches
an action so the UI can reflect the change straight away. During the
request the state change is marked as pending. For example, creating a
new object,
api.actionCreators.users.create({username: 'mark'});
will add,
{
username: 'mark',
status: 'pending'
}
to the state.
TODO what if 'status' is already a field of user?
On completion of the request the status is updated to saved
or
failed
as appropriate. E.g.
{
username: 'mark',
status: 'saved'
}
Available actions
The standard set of REST actions is available; list
,
retrieve
, create
and update
.
TODO
- add
delete
action
- add a
revert
action to revert optimistic changes if API request
fails.
- support APIs with custom endpoints
- integrate normalizr for flat object storage?