Skip to content

nikordaris/redux-async-action-middleware

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Redux Async Action Middleware

build status npm version npm downloads

Install

npm install --save redux-async-action-middleware

CommonJS

var asyncMiddleware = require('redux-async-action-middleware').default;

ES Modules

import asyncMiddleware from 'redux-async-action-middleware';

Why Do I Need This?

Just like Redux Thunk if you're not sure whether you need it, you probably don't.

Motivation

This middleware was inspired by Redux Thunk and Redux Async. After using a variation of Redux Async, I had realized that defining the three LOAD, SUCCESS, and FAIL redux event types were redundant and not necessary for my use. I also didn't like the non-standard organization of metadata vs payload. So following the lead of Redux Promise, I adopted the Flux Standard Action convention. The result is a combination of everything I liked from all three of these middleware modules.

Usage

Redux Thunk

There is a slight variation compared to Redux Thunk Composition

- function (dispatch, getState, extraArg) { ... }
+ function ({dispatch, getState, ...extraArgs}) { ... }

Note how instead of three arguments it is now a single object that contains dispatch, getState, and a spread of the extraArg object passed into the middleware creator. This was - in my opinion - a cleaner way to enable easy access to only the needed arguments by leveraging the destructuring feature.

Async Actions

import { createStore, applyMiddleware } from 'redux';
import asyncMiddleware from 'redux-async-action-middleware';
import axios from 'axios';
import rootReducer from './reducers';

const http = axios.create({
    baseURL: 'https://example.com/api',
    timeout: 1000,
    headers: {'X-Custom-Header': 'foobar'}
});

// Note: this API requires redux@>=3.1.0
const store = createStore(
  rootReducer,
  applyMiddleware(asyncMiddleware({http}))
);


const getThing = (id) => ({
    type: 'FETCH_THINGS',
    payload: ({http}) => http.get(`/thing/${id}`
});

const getStuffedThing = (id) => ({
    type: 'FETCH_STUFF_THING',
    payload: ({dispatch, http}) => http.get(`/stuff/${id}`)
        .then((result) => dispatch(getThing(result.data.thingId)))
});

store.dispatch(getThing(1));
store.dispatch(getStuffedThing(2));

Async Actions Redux Store Access

import React, {Component, PropTypes} from 'react';
import {bindActionCreators} from 'redux';
import {getFoo} from './reducers/foo';

@connect(state => ({foo: state.foo}),
    dispatch => bindActionCreators({getFoo})
)
export class Foo extends Component {
    static propTypes = {
        foo: PropTypes.object.isRequired,
        getFoo: PropTypes.func.isRequired
    }

    componentWillMount() {
        const {getFoo} = this.props;
        getFoo();
    }

    render() {
        const {foo: {meta: {loading, loaded}, payload}} = this.props;

        return (
            <div>
                {loading && <p>loading...</p>}
                {loaded && <p>{payload}</p>}
            </div>
        )
    }
}

About

Redux Async Middleware

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published