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

update-state

v1.0.7

Published

Update a state object or array with easy syntax

Downloads

40

Readme

Update State

Install

npm i update-state

Philosphy

This is to attempt to forumlate a more generalized way to update application state that has simple syntax and eliminates having to write a lot of reducers. The motivation behind creating this was to attempt to alleviate some complaints against redux, such as: "why do i have to change 4 files everytime i want to create an action?". In my opinion these complaints are not against redux itself but rather how a lot of people traditionally setup redux.

Quick explanation and example usage with Redux

You setup a single reducer that takes as the payload an updater. This updater contains what you want to update and matches the shape of the state. When comparing your updater to the state the reducer will do the following:

  • Any key value pairs on your updater are spread into the state.
  • If the updater shape and state shape both have an array at any point, the array values from the updater will be spread into the array on the state.
  • Anytime a function is encountered in the updater, it will be called with the first and only argument being the current value sitting on that point of the state. Whatever you return relaces the current value.
import { createStore } from "redux";
import { createActions } from "redux-actions";
import updateState, { mapWithUpdater, map } from "update-state";
// There are also named exports: filter and reduce that work on both objects and arrays.
// There first argument is the function and second the object or array

const initState = {
  account: {
    loginToken: "FH23h3cn2cSA3FDGr",
    userInfo: {
      id: 1,
      name: "me",
      favoriteNumbers: [4],
      things: [{ id: 1 }, { id: 2 }]
    }
  }
};

// create one single reducer that will be used for all actions
const reducer = function(state, { payload }) {
  if (!payload) return state;
  return updateState(state, payload);
};

// create the store with our single reducer
const store = createStore(reducer, initState);
const { dispatch } = store;

// create actions with the help of redux-actions
const actions = createActions({
  UPDATE_TOKEN: loginToken => ({ account: { loginToken } }),
  ADD_FAVORITE_NUMS: favoriteNumbers => ({
    account: { userInfo: { favoriteNumbers } }
  }),
  INCREMENT_FAVORITE_NUMS: (incBy = 1) => ({
    account: {
      userInfo: {
        favoriteNumbers: nums => map(n => n + incBy, nums)
      }
    }
  }),
  // mapWithUpdater allows your return value to behave as an updater.
  UPDATE_THINGS: fn => ({
    account: {
      userInfo: {
        things: things => mapWithUpdater(fn, things)
      }
    }
  })
});

dispatch(actions.updateToken("newtoken"));
// state.account.loginToken is now "newtoken"

dispatch(actions.addFavoriteNums([3, 2, 9]));
// state.account.userInfo.favoriteNumbers is now [4, 3, 2, 9]

dispatch(actions.incrementFavoriteNums(2));
// state.account.userInfo.favoriteNumbers is now [6, 5, 4, 11]

dispatch(
  actions.updateThings(function(thing) {
    return {
      name: "thing " + thing.id
    };
  })
);
// state.account.userInfo.things is now
// [
//   {id: 1, name: "thing 1"},
//   {id: 2, name: "thing 2"}
// ]

Deeper dive

What it is

The default export of Update State is a reducer function. Both arguments and the return value can be of any type, but to start off it is easier to think of them as being plain objects.

Argument 1: The state you wish to update

Argument 2: What is defined as an updater (defined in next section)

Returns: The new state that us produced from the updater

Definition of an updater

The updater should be an object that contains the data we want to update, and is the same shape as the state object. The goal is to be able to look at an updater and easily deduce which part of the state it aims to update as well as the payload that is being delivered.

example of an updater:

const updater = {
  account: {
    userInfo: { name: "new name" }
  }
};

By looking at this object we should be able to see what the payload is ({ name: "new name" }) as well as where it sits on the state object. (state.account.userInfo)

What it does

Update State will inspect the updater you pass to it and return a newly created / updated object. The below process is how the updater will be compared to the state and how the newly returned state will be generated and returned.

  • Any key value pairs on your updater are spread into the state.
  • If the updater shape and state shape both have an array at any point, the array values from the updater will be spread into the array on the state.
  • Anytime a function is encountered in the updater, it will be called with the first and only argument being the current value sitting on that point of the state. Whatever you return relaces the current value.