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

@mechanema/wedge

v1.0.0

Published

Separate two or more slices of a Redux store.

Downloads

13

Readme

Wedge

In classic mechanics, the wedge was used to separate two objects (or portions of a single object). It could also lift up or hold up a single object.

With Redux, this wedge is primarily used for separating slices within a store. This is done by providing some basic methods to create a reducer slice as a state machine, as well as aggregate everything into a root reducer.

Core Concepts

The wedge is focused on two closely related concepts around the Redux reducer: state machine and reducing boilerplate.

State Machine

Maintaining the simplicity of a reducer is paramount to the success of Redux. At the most elementary level, operating a reducer as a state machine can prevent unintended effects on the reducer store.

Stop me if you've experienced this before: you have an autocomplete component that performs an async request for data. While the asyc request is happening, you need to show some feedback to the user so they know to wait and that the app isn't broken. So, you add an isFetching value to the reducer. Of course, it's an autocomplete, and it's possible the user could have put invalid data. So, you add an isErrored value to the reducer as well. Both of these values are tracked throughout your reducer. Things get hairy because every related action could change one or both of those two values.

There is a better way: enter finite state machines. Instead of tracking these two values, what if we had a single one to denote not only the state of the reducer but also what actions are acceptable given the current reducer state.

createStateMachine is provided to transform a reducer into a state machine. Its only required parameter is a plain JS object acting like a hashmap between states and their reducers callbacks. This state machine method should then be registered with redux via combineReducers as it normally happens. By default, the initial state is INIT (and that's exported from wedge for convenience). Of course, you can change that value by providing it to createStateMachine as the second parameter. Also, be sure to provide a state key (exported as KEY_STATE) for tracking the reducer's state. Don't like that key name? It's configurable as the third parameter.

Reducing Boilerplate

But wait, there's more! As it often happens, you'll have a small piece of logic that can be called in multiple states. In an effort to support DRY-ness, we've made createStateMachine so that instead of a reducer callback for a state, you can also provide an array of reducer callbacks. Now, you can write really small reducer methods and aggregate them.

Writing a really small reducer method generally looks like a single

function (state = INITIAL_STATE, action) {
  if (action.type === SOME_ACTION) {
    const changedState = state.merge({/* changes */});
    // your logic here

    return changedState;
  }

  return state;
}

That looks like a bit of boilerplate, no? Well, createReducer comes to the rescue. It takes two parameters: the expected action (SOME_ACTION above), and a callback for what to change based on the action's payload ((state, actionPayload, action) => state.merge({})).

In traditional redux setups, you'd then import all of these reducers into a single root reducer file and push them through combineReducers from Redux. Why not cut that out and push reducers as they're defined. For that effort, we have registerReducer to add a reducer to a central registry with a given reducer key (called a namespace here). And for convenience, there's a registerStateMachine function which first calls createStateMachine and then registerReducer to get a state machine reducer quickly added to the reducer registry. Then, in your root reducer file, you only need to call createRootReducer() in order to get the same end result as writing that single hashmap and passing it to combineReducers but with a little less boilerplate.

Immutable

Data immutability is important for several reasons, so we are enforcing the usage of ImmutableJS. The aggregrator (register* and createRootReducer methods) use Redux-Immutable under the hood.

Example

Check out the example directory for a full example of a wedge-backed reducer.