npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

redux-jsonapi

v1.1.3

Published

Redux reducer, actions, and serializers for JSON:API

Downloads

50

Readme

Redux JSON:API

Travis CI Code Climate Test Coverage

Redux JSON:API is a collection of actions and reducers for Redux that help ease the use of a JSON:API compliant API.

JSON:API is amazing for data transport, but once a client has the data it can be a little frustrating to work with. Redux JSON:API takes the guess-work and bike-shedding about how to structure, store, and use your JSON:API data in a Redux application.

Instalation

To install the stable version:

npm install --save redux-jsonapi

Usage

The Basics

The following will fetch a widget from GET http://example.com/widgets/1 (including it's associated foobars) add it to the application state under api (indexed by it's ID), and output the new state to the console.

import { createStore, combineReducers } from 'redux';
import { apiReducer, apiActions, createApiMiddleware } from 'redux-jsonapi';

const reducers = combineReducers({
  api: apiReducer
})

const apiMiddleware = createApiMiddleware('http://example.com');

const store = createStore(reducers, applyMiddleware(apiMiddleware);

store.subscribe(() => {
  console.log(store.getState().api);
});

store.dispatch(apiActions.read({ id: 1, _type: 'widgets' }, {
  params: {
    include: 'foobars'
  },
}));

Creating a widget via the API and adding it to the application state on success isn't much more complicated:

store.dispatch(apiActions.write({ _type: 'widgets', name: 'Super Cool Widget' }));

Updating an existing record is nearly identical - simply make sure the resource has an ID property:

store.dispatch(apiActions.write({ _type: 'widgets', id: 1, name: 'Super Cool Widget With A New Name' }));

Deleting a record is very similar:

store.dispatch(apiActions.remove({ _type: 'widgets', id: 1 }));

Nested Resources

To access the entities on a nested URL, provide an array of parent resources to the action. The following will fetch the entities from GET http://example.com/widgets/1/doodads:

store.dispatch(apiActions.read([{ _type: 'widgets', id: 1 }, { _type: 'doodads' }]));

Note: the order of resources in the array determines the order of nesting.

Custom Headers

You can extend the default headers by simply passing an object as 2nd parameter into createApiMiddleware.

const apiMiddleware = createApiMiddleware('http://example.com', {
    Authorization:  'JWT Token'
});

With each apiActions method you can provide additional headers as well

store.dispatch(apiActions.read({ id: 1, _type: 'widgets' }, {
  params: {
    include: 'foobars'
  },
  headers: {
    cookies: 'MyCookie'
  }
}));

Using Data

Data received from the JSON:API store is normalized into categories by resource type, and indexed by the resource's ID. The structure looks something like the following:

{
  api: {
    widgets: {
      1: {
        id: 1,
        type: 'widgets',
        attributes: {
          name: 'Super Cool Widget',
        },
        relationships: {
          doodad: {
            data: {
              id: 1,
              type: 'doodads',
            }
          }
        }
      },
      2: { ... },
    },
    doodads: {
      1: {
        id: 1,
        type: 'doodads',
        attributes: {
          name: 'Nifty Doodad',
        },
      },
      2: { ... },
    }
  }
}

Since often the data that we receive from the API contains associations to other resources, this isn't a very easy structure to work with out of the box. Redux JSON:API contains utilities that make serializing and deserializing resources between the JSON:API structure and a vanilla Javascript object structure much easier.

The following will fetch a widget from the API at /widgets/1, and upon being loaded into the Redux state it will log a deserialized instance of it to the console.

import { apiActions, deserialize } from 'redux-jsonapi';

store.subscribe(() => {
  const { api } = store.getState();
  const widget = deserialize(api.widgets[1], api);
  console.log(widget);
});

store.dispatch(apiActions.read({ id: 1, _type: 'widgets' }));

The denormalized instance looks something like this:

const widget = {
  _type: 'widgets',
  id: 1,
  name: 'Super Cool Widget',
  doodad: function() { // Calling this returns the associated doodad }
}

With this new denormalized resource, we can access the widget's name via widget.name, and it's associated doodad by calling widget.doodad().

When it comes time to update the widget, simply change it's values and dispatch the apiActions.write action with the object.

widget.name = 'New Name';
widget.doodad = () => newDoodad;
store.dispatch(apiActions.write(widget));

Example

See the example directory.

License

MIT