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-shelf

v0.0.9

Published

Helper reducers and actions to take away your boilerplate code from both Data and Communication state types

Downloads

5

Readme

Redux Shelf

Redux Shelf is a library that provide a simple API to create and manage both Entity and Communication state of your application using Redux reducers, by managing for you all the boilerplate necessary to do that.

Build Status

Influences

React applications contains several types of state wich we have to manage. James K. Nelson, on this great article, identify 5 types of them. On this library we are focused on two of the 5 types: Data state, that we prefer to call Entity state, and Communication state. Below you can find a summary of each type:

Data State

"Data state covers information which your application temporarily stores about the big wide world. That is, it covers your business data."

"Every piece of received Data has a type, and a selector which exactly specifies which data was received."

Communication State

"This type of state covers the seemingly simple yet somewhat thorny information which represents things like loading spinners and error messages."

"Communication state is the status of any not-yet-complete requests to other services."

"This means that all of the following are communication state:

  • The type/selector for any Data you expect to receive
  • The type, selector and expected change of any operations you have requested on Data
  • The error messages for anything which didn’t go quite as planned."

With Redux Shelf you can reduce Entity and Communication state management boilerplate in your application, by using a simple and easy to learn API.

Installation

yarn add redux-shelf

or

npm install redux-shelf

Configuration

// reducers/index.js
import { combineReducers } from 'redux';

import { entities, communication } from 'redux-shelf';

export default (appReducers = combineReducers({
  entities,
  communication,
}));

API

Bellow you can find the description of the API provided by Redux Shelf library.

Entity

  • set(type, payload): Overrides the current state of an Entity.
  • update(type, payload): Merge the current state of an Entity with new state.
  • remove(type, selector): Remove a record of an Entity.
  • idsOf(type): Returns the array of ids of an Entity type provided as parameter.
  • contentOf(type, selector): Returns content object of an specific Entity record, identified by its type and selector provided as parameters.
  • of(type, selector?): It's an alias for idsOf and contentOf methods. When only type parameter is given to of method it behaves like idsOf call, while when selector parameter is also provided of method will behave like contentOf call.

Note: By using Entity Actions API we're assuming that you'll normalize Entity data on ids/content form. So, you must either use normalize function provided by library or use another one that works similarly (check Utils section).

Communication

  • starting(type, selector?): Sets communication status with the STARTING status for the given entity type and selector.
  • done(type, selector?): Sets communication status with the DONE status for the given entity type and selector.
  • fail(type, selector|error, error): Sets communication status with the FAIL status for the given entity type, selector and/or error.
  • cancel(type, selector?): Sets communication status with the CANCEL status for the given entity type and selector.
  • of(type, selector?): Returns an object with loading and error.

Utils

  • normalize(payload, key?): Normalizes a given payload to ids/content shape. If key parameter is not provided, the function will normalize the payload by id property, assuming that it has it. The valid values for payload parameter are: An object or an array of objects. If the value provided as payload parameter is invalid, the function will return a default normalized object { ids: [], content: {} }. See the examples below:
const payload = [{ id: 1, name: 'Product 1' }, { id: 2, name: 'Product 2' }];
console.log(normalize(payload, 'id'));
// console output
/*
  {
    ids: [1, 2],
    content: {
      1: { id: 1, name: 'Product 1' },
      2: { id: 2, name: 'Product 2' },
    },
  }
*/

...

const payload = { id: 1, name: 'Product 1' };
console.log(normalize(payload));
// console output
/*
  {
    ids: [1],
    content: {
      1: { id: 1, name: 'Product 1' },
    },
  }
*/

...

const payload = [
  { identifier: 1, name: 'Product 1' },
  { identifier: 2, name: 'Product 2' },
  { id: 3, name: 'Product 2' },
  true,
  null,
  42,
];
console.log(normalize(payload, 'identifier'));
// console output
/*
  {
    ids: [1, 2],
    content: {
      1: { identifier: 1, name: 'Product 1' },
      2: { identifier: 2, name: 'Product 2' },
    },
  }
*/

Usage

// userActions.js
import { entities, communication, normalize } from 'redux-shelf';

// Here I assuming that you're using some middleware to handle
// asynchronous actions, for example, Redux Thunk
export function fetchUsers() {
  return async (dispatch) => {
    dispatch(communication.starting('users'));

    try {
      const url = 'endpoint_to_get_users_data';
      const request = await fetch(url);
      const payload = request.json();

      dispatch(entities.set('users', normalize(payload)));
      dispatch(communication.done('users'));
    } catch (e) {
      dispatch(communication.fail('users', e));
      console.log(e);
    }
  };
}

...

// UserList.jsx
export const UserList = ({ loading, error, userIds }) => {
  if (error) {
    return <div>Failed to load users</div>
  }

  if (loading) {
    return <div>Loading...</div>
  }

  return (
    <div>
      {userIds.map(userId => <UserItem key={userId} userId={id} />)}
    </div>
  );
);

export default connect(
  ({ entities, communication }) => {
    const {
      loading,
      error,
    } = communication.of('users');

    const userIds = entities.idsOf('users');

    return {
      loading,
      error,
      userIds,
    };
  },
)(UserList);

...

// UserItem.jsx
export const UserItem = ({ name }) => (
  <span>
    {name}
  </span>
);

export default connect(
  ({ entities }, { userId }) => {
    const user = entities.contentOf('users', userId);

    return {
      name: user.name,
    };
  },
)(UserItem);

License

MIT