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-normalized-crud

v2.1.1-beta7

Published

An attempt to standardize restful calls within a growing redux application

Downloads

43

Readme

redux-normalized-crud

Updated DOCS coming soon

npm version

An attempt to standardize RESTful calls and responses within a growing redux application.

Installation

To install the latest version:

npm install --save redux-normalized-crud

This assumes you are using npm as your package manager.

This library uses:

In it's current version, you're expected to use these libraries in your application:

##What do you get out of using it? This library provides you with a suite of standardized sagas, reducers, action creators, and selectors to make all CRUD calls super easy.

  • Standardized server responses turned into entities
  • Standardized paging with grouping
  • Optimistic update, create, and delete server requests out of the box

##Example Usage:

####Create a config file that exports an object

  // config.js
  import { normalize } from 'normalizr';
  export default {
    baseUrl: 'http://localhost:3000/api/',
    // This is a callback you hook into when the server comes back with an OK (Status 200) response
    // You normalize it depending on how your sever returns paged lists, or resources
    normalizeResponse: (response, schema) => {
      let normalizedResult;
      if (Array.isArray(response.data) && 'data' in response) {
        // Paged Result set
        normalizedResult = normalize(response.data, [schema]);
      } else if(Array.isArray(response)) {
        // Just an array of items
        normalizedResult = normalize(response, [schema]);
      } else {
        // Just an object
        normalizedResult = normalize(response, schema);
      }
      return normalizedResult;
    },
    /*
       Here you define where the total items key is on the response object
       In this case the response looks like:
       
       {
        total: 5,
        data: [
          {},
          ... more data
        ]
       }
    */
    paginationResponseKeys: {
      totalItems: 'total'
    },
    // This is the callback gets triggered when the server response is not Ok 
    onServerError: (e) => {
      // This is a fetch response
      const statusCode = e.response.statusCode;
      // do something
    }
  };

Note: This can be defined on for every resource in your system or you could define 1 per resource if you wanted

Register your entity

  // post.js
  import { schema } from 'normalizr';
  import { registerEntity } from 'redux-normalized-crud';
  
  // Grab the config file we just made
  import config  from './config';
  
  // Use normalizr here to create your entity
  const postEntity = new schema.Entity('POSTS');
  
  export const {
    sagas, // All crud actions for a given entity (this gets registered with your redux-saga)
    constants, // An object full of post constants that contain all of the crud actions
    creators, // An object full of all the action creators for the post entity
    entitySelector, // A helpful selector that is ready to key off the post entities
    groupSelector, // Another helpful selector ready to key off of your defined paged lists
  } = registerEntity(config, postEntity);

Register the sagas and enhance your reducer

  // store.js
  import { createStore, applyMiddleware, compose } from 'redux';
  import createSagaMiddleware from 'redux-saga';
  import { combineWithCrudReducers } from 'redux-normalized-crud';
  import { sagas as postCrudSagas } from './post';
  
  // SAGAS
  const mySaga = function* () {
    yield [
      postCrudSagas(),
      // any other crud sagas go here
    ];
  };
  
  const sagaMiddleware = createSagaMiddleware();
  
  /*
    Wrap your reducer with "combineWithCrudReducers". This acts the same as
    combine with reducers. You can put other reducers in that empty object.
  */
  const rootReducer = combineWithCrudReducers({});
  
  const initialState = {};
  
  const enhancer = applyMiddleware(sagaMiddleware);
  
  const store = createStore(
    rootReducer,
    initialState,
    enhancer
  );
  
  sagaMiddleware.run(mySaga);
  
  export default store;

Fire off actions in your components

// Posts.jsx
import React, {  PropTypes } from 'react'
import { connect } from 'react-redux';
import {
  creators as PostCrudActions,
  entitySelector as postSelector,
  groupSelector as pagedPosts
} from './post-redux';

class PostList extends React.Component {
  componentWillMount() {
    const { getPosts } = this.props;
    getPosts({});
  }

  render() {
    const { posts, geting } = this.props;

    if(loading) return <div> Loading... </div>;

    return (
      <div>
       {
        posts.map(p => (
          <div key={p.id}>
            <Link to={`/post/${p.id}`}>
              {p.title}
            </Link>
          </div>
        )
        )}
      </div>
    )
  }
}

PostList.propTypes = {
  posts: PropTypes.arrayOf({
    name: PropTypes.string
  })
};

export default connect(state => {
  const pagedData = pagedPosts()(state);
  const posts = pagedData.ids.map(id => postSelector(id)(state));
  return { posts, loading: pagedData.isLoading }
}, 
{
  getPosts: PostCrudActions.getRequest
})(PostList);

  
Your State will now look like:

redux store example