Skip to content

temnoregg/redux-api

 
 

Repository files navigation

Redux-api

Build Status NPM version Coverage Status

Inspired by Redux-rest and is recommended to work with Redux.

Install

with npm

npm install redux-api --save

with bower

bower install redux-api --save

=======

Documentation

import reduxApi, {transformers} from "redux-api";

reduxApi(options, fetchAdapter)

  • options - configuration rest-api endpoints

type: Object return: {reducers, actions} - reducers have to as parameter to createStore (see example section). actions (see actions section) default: {} example: Simple endpoint definition GET /api/v1/entry where response is Object

{
  entry: "/api/v1/entry",
}
// equivalent
{
  entry: {
    url: "/api/v1/entry"
  }
}
// equivalent
{
  entry: {
    url: "/api/v1/entry",
    transformer: transformers.object, //it's default value
    options: {}                       //it's default value
  }
}
// equivalent
{
  entry: {
    url: "/api/v1/entry",
    transformer: transformers.object, //it's default value
    options: function(url, params) {  //it's default value
      return {};
    }                       
  }
}

url - endpoint for rest api

type: String transformer - response transformer type: Function default: transformers.object example: It's a good idea to write custom transformer for example you have responce json { "title": "Hello", "message": "World" } Custom transformer js function customTransformer(data) { if (!data) { return {title: "", message: ""}; } return { title: (data.title || ""), message: (data.message || "")}; } options - Options for rest-api backend. function(url, options) > type: Object > default: null > example: if you use whatwg-fetch backend options: { method: "post", headers: { "Accept": "application/json", "Content-Type": "application/json" } }

  • adaptersFetch - adapter for rest backend using fetch API for rest whatwg-fetch

type: Function default: null example:

// available adapters
import adapterFetch from "redux-api/adapters/fetch";

actions

import reduxApi, {transformers} from "redux-api";
const rest = reduxApi({
  entries: "/api/v1/entry",
  entry: {
    url: "/api/v1/entry/:id",
    options: {
      method: "post"
    }
  }
});
const {actions} = rest;

/*
initialState for store
store = {
  entries: {
    loading: false, // request finish flag
    sync: false,    // data has loaded minimum once
    data: {}        // data
  },
  entry: { loading: false, sync: false, data: {} },
}
*/

// In component with redux support (see example section)
const {dispatch} = this.props;
dispatch(rest.actions.entries()); // GET "/api/v1/entry"
dispatch(rest.actions.entry({id: 1}, {
  body: JSON.stringify({ name: "Hubot", login: "hubot"
}}));  // POST "/api/v1/entry/1" with body

//also available helper methods
dispatch(rest.actions.entries.reset()) // set initialState to store
dispatch(rest.actions.entries.sync()) // this mathod save you from twice requests
                                    // flag `sync`. if `sync===true` requst
                                    // wouldnt execute

reducerName

Sometimes though, you might want named actions that go back to the same reducer. For example:

import reduxApi, {transformers} from "redux-api";
const rest = reduxApi({
  getUser: {
    reducerName: "user"
    url: "/user/1", // return a user object
  }
  updateUser: {
    reducerName: "user"
    url: "/user/1/update",
    options: {
      method: "post"
    }
  }
});
const {actions} = rest;

// In component with redux support (see example section)
const {dispatch} = this.props;
dispatch(rest.actions.getUser()); // GET "/api/v1/entry"
dispatch(rest.actions.updateUser({}, {
  body: JSON.stringify({ name: "Hubot", login: "hubot"})
}));  // POST "/api/v1/entry/1" with body

In the above example, both getUser, and updateUser update the same user reducer as they share the same reducerName

For example used es7 javascript, Redux@1.0.0-rc, but it's pretty simple to migrate this code to Redux@v0.12.0

###Example rest.js

import "whatwg-fetch";
import reduxApi, {transformers} from "redux-api";
import adapterFetch from "redux-api/adapters/fetch";
export default reduxApi({
  // simple edpoint description
  entry: `/api/v1/entry/:id`,
  // complex endpoint description
  regions: {
    url: `/api/v1/regions`,
    // reimplement default `transformers.object`
    transformer: transformers.array,
    // base endpoint options `fetch(url, options)`
    options: {
      header: {
        "Accept": "application/json"
      }
    }
  }
}, adapterFetch(fetch)); // it's nessasary to point using rest backend

index.jsx

import React, {PropTypes} from "react";
import { createStore, applyMiddleware, combineReducers } from "redux";
import thunk from "redux-thunk";
import { Provider } from "react-redux";
import rest from "./rest"; //our redux-rest object

const createStoreWithMiddleware = applyMiddleware(thunk)(createStore);
const reducer = combineReducers(rest.reducers);
const store = createStoreWithMiddleware(reducer);

@connect((state)=> ({ entry: state.entry, regions: state.regions }))
class Application {
  static propTypes = {
    entry: PropTypes.object.isRequired,
    regions: PropTypes.array.isRequired,
    dispatch: PropTypes.func.isRequired
  }
  componentDidMount() {
    const {dispatch} = this.props;
    // fetch `/api/v1/regions
    dispatch(rest.actions.regions.sync());
    //specify id for GET: /api/v1/entry/1
    dispatch(rest.actions.entry({id: 1}));
  }
  render() {
    const {entry, regions} = this.props;
    const Regions = regions.data.map((item)=> <p>{ item.name }</p>)
    return (
      <div>
        Loading regions: { regions.loading }
        <Regions/>
        Loading entry: {entry.loading}
        <div>{{ entry.data.text }}</div>
      </div>
    );
  }
}

React.render(
  <Provider store={store}>
    { ()=> <Application /> }
  </Provider>,
  document.getElementById("content")
);

Store state schema

const rest = reduxApi({
  user: "/user/1"
});
// initialState
{
  user: {
    sync: false,    // State was update once
    syncing: false, // State syncing is in progress
    loading: false, // State updating is in progress
    error: null,    // responce error
    data: []        // responce data
  }
}

Url schema

/api/v1/user/:id

rest.actions.user({id: 1}) // /api/v1/user/1

/api/v1/user/(:id)

rest.actions.user({id: 1}) // /api/v1/user/1

/api/v1/user/(:id)

rest.actions.user({id: 1, test: 2}) // /api/v1/user/1?test=2

About

Flux REST API for redux infrastructure

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages

  • JavaScript 100.0%