redux-loader

Loader component for Redux

Usage no npm install needed!

<script type="module">
  import reduxLoader from 'https://cdn.skypack.dev/redux-loader';
</script>

README

Redux Loader

Codeship Status for Versent/redux-loader

A high order component and request management utility for Redux.

  • Loads resources and passes them to the child components via props.
  • Keeps tracks of requests already done and avoids duplicate requests.

Usage

Your Redux application must include the Redux-Loader reducer. It needs to be under the requests key:

import reduxLoader from 'redux-loader'

const allReducers = combineReducers({
  requests:        reduxLoader.reducer,
  ...
})

const store = finalCreateStore(allReducers)

This reducer is used for keeping track of pending and completed requests.

Then create a high order component to load the data:

import reduxLoader    from 'redux-loader'
import { connect }    from 'react-redux'
import _              from 'lodash'
import Show           from './Show.jsx'
import Busy           from './Busy.jsx'

const Loader = reduxLoader.create({

  // React component to show while loading the resources
  busy:      Busy,

  // React component what will be rendered when resources are loaded
  component: Show,

  /*
  `resources` is a map with resources to load before rendering the component above
  this can be one or many.

  The component above will receive these resources as props e.g. post
  */
  resources: {

    /*
    These resources will be send to the child component via props.

    You must return a function for each resource you want to load.

    This function takes:

    - options.props
    - options.context
    - options.dispatch

    You need to pass the state you need to the Loader using connect.
    You function will be called again each time your component receives new props,
    meaning that you will always have fresh props.

    This function must return an object with keys {id, find, load}
    */
    user(options) {

      const userId = options.props.userId
      const id = `/users/${userId}`

      return {
        /*
        Loader must return an id for the current resource.
        This id will be used to keep track of request already done.
        */
        id,

        /*
        Ask to load the resource/s
        This is triggered when a request has not been done before.
        This is determined by `id` above.
        */
        load() {
          const action = actions.fetchOne(userId)
          return options.dispatch(action)
        },

        /*
        Find the resource/s in your state.

        This is called when a request has been done successfully.
        Loader uses the given `id` above to determine this.
        */
        find() {
          return _.find(options.props.users, {id: userId})
        },

      },

      /*
      You may also load several resources at once
      */
      posts(options) {
        ...
      }

    }
  }
});

// You need to pipe Loader through connect
export default connect(state => state)(Loader)

Example app here

How does it work

Heavily inspired by Marty